MongoDB更新时如何正确使用$getField为新字段赋现有字段值
MongoDB更新时引用同文档字段值的正确方法
现有文档结构
目标集合内的文档结构如下:
{ _id: ObjectId("5c8eccc1caa187d17ca6ed16"), city: 'ALPINE', zip: '35014', loc: { y: 33.331165, x: 86.208934 }, pop: 3062, state: 'AL' }
需求与错误复现
需求:为文档新增population字段,字段值和同文档pop字段取值一致。
尝试执行的更新语句:
db.collection.updateOne({}, {$set: {"population": { $getField: "pop" }}})
执行后不符合预期,population被存成了普通对象,内容就是表达式本身:
{ _id: ObjectId("5c8eccc1caa187d17ca6ed16"), city: 'ALPINE', zip: '35014', loc: { y: 33.331165, x: 86.208934 }, pop: 3062, state: 'AL', population: { '$getField': 'pop' } }
错误原因
普通更新模式下(更新参数传普通对象),MongoDB会把$set对应的值全部当做字面量直接写入文档,不会识别、求值聚合运算符(比如$getField)。
正确写法
MongoDB 4.2及以上版本支持聚合管道形式的更新,只需要把更新阶段的参数包裹在数组里,MongoDB就会按聚合语法解析管道内的表达式,支持引用同文档字段、做运算。
引用同文档普通字段直接使用$字段名的格式即可,不需要额外调用$getField($getField仅用于读取名称含特殊字符、以$开头的特殊字段场景),正确语句如下:
db.collection.updateOne( // 替换成你的实际筛选条件,示例留空则匹配集合第一条文档 {}, [ { $set: { population: "$pop" } } ] )
执行后文档新增的population字段会正确取到pop的数值3062,符合预期。
如果你使用的MongoDB版本低于4.2,不支持聚合管道更新,需要先通过查询操作拿到目标文档的
pop字段值,再把值作为字面量传入$set完成更新。
内容的提问来源于stack exchange,提问作者Laughing_Man
相关产品推荐
相关产品推荐

