MongoDB如何基于现有条目值为已有集合新增UUID类型字段
问题根因
之前的更新语句失效,核心是两点:
- 非管道模式的
update/updateMany不支持逐文档引用当前记录的字段做动态计算,UUID("$_id")会在语句发送到Mongo服务端前,就被客户端提前解析执行,根本拿不到每个文档对应的_id实际值 - 直接写
"$_id"在非管道场景下不会被识别为字段引用,最终生成无效的UUID("----")值
解决方案
适用于MongoDB 4.2及以上版本(推荐)
使用聚合管道模式的批量更新,第二个参数传入数组包裹的更新操作,Mongo会逐文档读取字段值完成类型转换:
db.Users.updateMany( {}, [ { $set: { UserId: UUID("$_id") } } ] )
关键区别:更新操作被数组
[]包裹时,MongoDB会将内部逻辑识别为聚合管道,此时$字段名语法才会被正确解析为当前文档的对应字段引用,逐文档完成计算。
执行完成后查询任意文档,即可得到目标结构:
{ "_id": "fe83f869-154e-4c26-a5db-fb147728820f", "userName": "alex", "UserId": UUID("fe83f869-154e-4c26-a5db-fb147728820f") }
适用于MongoDB 4.2以下版本
低版本不支持管道更新,可通过游标循环搭配批量写入优化性能:
const ops = [] db.Users.find({}, {_id: 1}).forEach(doc => { ops.push({ updateOne: { filter: {_id: doc._id}, update: {$set: {UserId: UUID(doc._id)}} } }) // 每1000条批量提交一次,减少网络开销 if (ops.length === 1000) { db.Users.bulkWrite(ops) ops.length = 0 } }) // 提交剩余待执行操作 if (ops.length > 0) { db.Users.bulkWrite(ops) }
内容的提问来源于stack exchange,提问作者StasM
相关产品推荐
相关产品推荐

