MongoDB跨集合新增字段时updateOne无文档更新问题求解
问题原因及解决方案
常见原因(按出现概率排序)
- ID匹配异常
聚合返回结果中的_id和CarModifications集合中存储的_id类型不匹配,比如聚合返回的是字符串类型_id,但集合中实际存储的是ObjectId类型,导致updateOne的匹配条件{_id: result._id}无法命中任何文档,自然没有更新记录。
你可以在循环中增加打印逻辑校验:
.forEach(function(result) { // 打印_id值和类型确认 print(result._id, typeof result._id) let updateRes = db.CarModifications.updateOne({_id: result._id}, {$set: {"CarType": result.CarType}}) // 打印更新结果确认匹配和修改数 printjson(updateRes) })
如果返回结果中matchedCount为0,就可以确认是ID匹配问题。
- 无实际内容变更
如果matchedCount大于0但modifiedCount为0,说明你要写入的CarType值和目标文档中已有的CarType值完全一致,MongoDB默认不会执行无变化的更新操作,因此不会产生更新记录。 - 权限问题
当前使用的数据库账号仅拥有CarModifications集合的读权限,没有写权限,写入请求被数据库权限系统拦截,也会出现无更新的情况。 - 跨库指向错误
如果聚合操作针对的是其他库的CarModifications集合,但是更新操作默认写入当前数据库的同名集合,也会出现聚合有结果但更新无响应的问题。
优化方案
MongoDB 4.2及以上版本可以直接使用聚合的$merge阶段直接完成集合内更新,无需客户端循环执行update,性能更高也可以避免客户端层面的逻辑错误:
db.CarModifications.aggregate([ { $lookup: { from: "CarTypes", localField: "CarTypeID", foreignField: "CarTypeID", as: "carType" } }, { $addFields: { // 直接取数组第一个元素的_id,不需要单独unwind CarType: {$first: "$carType._id"} } }, { $project: { CarType: 1 } }, { $merge: { into: "CarModifications", on: "_id", whenMatched: "merge", whenNotMatched: "discard" } } ])
内容的提问来源于stack exchange,提问作者Oleg Volkov
相关产品推荐
相关产品推荐

