如何在MongoDB更新或聚合操作中生成唯一的ObjectId?
原因说明
你当前写法里的new ObjectId()是在mongo shell本地执行的,整个更新请求发送到数据库前就已经生成了一个固定的ObjectId值,所以所有匹配到的子文档都会被赋值为同一个_id。
推荐解决方案(MongoDB 4.2及以上版本可用)
使用带聚合管道的更新操作,遍历数组时为每个缺失_id的子文档单独生成新的ObjectId,即可保证唯一性:
db.jobs.updateMany( {}, [ { $set: { artifacts: { $map: { input: "$artifacts", in: { $mergeObjects: [ "$$this", { _id: { $cond: [ { $ne: [{ $type: "$$this._id" }, "missing"] }, "$$this._id", new ObjectId() ] } } ] } } } } } ] )
低版本兼容方案(适用于所有MongoDB版本)
如果你的数据库版本低于4.2,不支持聚合管道更新,可以用游标遍历文档逐个处理:
db.jobs.find().forEach(job => { if (!Array.isArray(job.artifacts)) return job.artifacts.forEach(item => { if (!item._id) item._id = new ObjectId() }) db.jobs.replaceOne({ _id: job._id }, job) })
这种方式是逐个处理每个子文档,每个_id都是单独生成的,不会出现重复问题,数据量较大时执行效率会低于批量更新。
内容的提问来源于stack exchange,提问作者Brian Drew
相关产品推荐
相关产品推荐

