Mongoose批量操作执行$push更新报错如何解决
报错原因
这个错误由更新操作写法错误直接触发:
- 你将
$push更新操作符嵌套在了$set的参数对象中,MongoDB会把$set接收的对象识别为「待赋值的普通字段集合」,这类场景下不允许出现$开头的字段名,因此抛出异常。 - 原代码还存在2个隐藏问题:
docUpdates数组中存储主键的字段名是id,循环拼接查询条件时读取的是docUpdates[i].docId,字段名不匹配会导致查询条件为空,更新错配数据- 第二条更新记录的status值存在拼写错误:
compelted的正确拼写为completed
修复方案
方案1:修正原生有序批量操作写法
将普通字段赋值、数组追加操作拆为同级的更新操作符,禁止把$push这类操作符嵌套在$set内部,修正后可直接运行的代码如下:
const docUpdates = [ { _id: docId1, // 统一用_id存储主键,和查询条件字段对齐 status: "created", pushRecord: { status: "created", referenceId: referenceId, createdTimestamp: "2022-06-14T00:00:00.000Z" } }, { _id: docId2, status: "completed", pushRecord: { status: "completed", // 修正拼写错误 referenceId: referenceId, createdTimestamp: "2022-06-14T00:00:00.000Z" } }, ]; // 初始化有序批量操作实例 const bulkUpdate = Model.collection.initializeOrderedBulkOp(); for (const item of docUpdates) { bulkUpdate.find({ _id: item._id }).updateOne({ $set: { status: item.status }, // $set仅承载普通字段的赋值逻辑 $push: { updates: item.pushRecord } // $push和$set为同级更新操作符,独立声明 }) } // 执行批量操作,必须加await等待结果,否则会出现未捕获的Promise异常 const res = await bulkUpdate.execute();
方案2:使用Mongoose封装的bulkWrite API(推荐)
不需要手动初始化批量操作实例,Mongoose会自动处理底层逻辑,写法更简洁,出错概率更低:
// 构造批量操作数组 const bulkOps = docUpdates.map(item => ({ updateOne: { filter: { _id: item._id }, update: { $set: { status: item.status }, $push: { updates: item.pushRecord } } } })); // 执行批量操作,ordered: true对应原有序批量操作的语义 const res = await Model.bulkWrite(bulkOps, { ordered: true });
核心注意点
MongoDB所有更新操作符($set/$push/$inc/$pull等)都必须放在update参数的顶层同级位置,禁止将一个更新操作符嵌套在另一个更新操作符的参数对象中,否则都会触发同类的字段不允许错误。
内容的提问来源于stack exchange,提问作者KK2491
相关产品推荐
相关产品推荐

