You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在NestJS中使用Mongoose更新带关联条件的Mongo集合失败

NestJS中Mongoose更新MongoDB文档未生效问题

问题描述

在NestJS中使用Mongoose操作MongoDB,完成账单金额计算后,尝试将符合条件的Event文档的billed字段更新为true,但更新操作无报错却未生效。

相关代码定义

Interfaces

export interface ISubscription {
  name: string;
  category: string;
  ....
}
export interface IPlan {
  name: string;
  status: string;
  charges?: [ICharge];
}
export interface IEvent {
  subscription: ISubscription;
  plan: IPlan;
  date: Date;
  type: string;
  amount: number;
  data: any;
  billed: boolean;
}

Subscription Schema

interface SubscriptionDocument extends ISubscription, Document {}

const SubscriptionSchemaFields: Record<keyof ISubscription, any> = {
  name: String,
  category: String,
 ........
};
const SubscriptionSchema = new Schema(SubscriptionSchemaFields);

const Subscription = model<SubscriptionDocument>(
  'Subscription',
  SubscriptionSchema,
);

export { SubscriptionDocument, SubscriptionSchema, Subscription };

Event Schema Definition

interface EventDocument extends IEvent, Document {}

const EventSchemaFields: Record<keyof IEvent, any> = {
  subscription: {
    type: Schema.Types.ObjectId,
    ref: 'Subscription',
  },
  plan: {
    type: Schema.Types.ObjectId,
    ref: 'Plan',
  },
  date: Date,
  type: String,
  amount: Number,
  data: Object,
  billed: {
    type: Boolean,
    default: false,
  },
};
const EventSchema = new Schema(EventSchemaFields);

const Event = model<EventDocument>('Event', EventSchema);

export { EventDocument, EventSchema, Event };

账单计算与更新操作

账单金额聚合查询

const balanceCalc = await this.eventModel.aggregate([
  {
    $match: {
      subscription: { $eq: Types.ObjectId(instantBill.subscription) },
      plan: { $eq: Types.ObjectId(instantBill.plan) },
      billed: { $eq: false },
    },
  },
  {
    $group: {
      _id: null,
      sumamount: { $sum: '$amount' },
    },
  },
]);

未生效的更新代码

const eventupdate = await this.eventModel.updateMany(
  {
    'subscription._id': subscriptionId,
    'plan._id': planId,
    billed: false,
  },
  { $set: { billed: true } },
);

其中subscriptionId和planId均为字符串,预期匹配对应subscription和plan的未账单化Event并更新,但操作无报错却未生效。

解决方案

问题出在更新条件的写法和ID类型不匹配:

  1. 字段路径错误:Event Schema中subscription和plan是直接存储的ObjectId类型,不是嵌套对象,因此'subscription._id'这种嵌套路径写法无法匹配到文档。
  2. ID类型不匹配:数据库中存储的是ObjectId类型,而传入的subscriptionId和planId是字符串,需要转换为Mongoose的ObjectId才能匹配。

修正后的更新代码如下:

import { Types } from 'mongoose';

// 转换字符串ID为ObjectId
const subId = Types.ObjectId(subscriptionId);
const pId = Types.ObjectId(planId);

const eventupdate = await this.eventModel.updateMany(
  {
    subscription: subId,
    plan: pId,
    billed: false,
  },
  { $set: { billed: true } },
);

可以参考聚合查询中的条件写法,保持一致的匹配逻辑,避免出现路径或类型错误。

内容的提问来源于stack exchange,提问作者Mujibur Rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:58:29