MongoDB聚合管道中创建identifier字段并赋值ObjectId的问题
解决MongoDB聚合中提取$oid字段的报错问题
集合记录示例
{ "_id": "{\"_id\": {\"$oid\": \"67a20f0adee77ef71adfe8bc\"}, \"copyingData\": true}", "operationType": "insert", "fullDocumentBeforeChange": null, "fullDocument": "{\"_id\": {\"$oid\": \"67a20f0adee77ef71adfe8bc\"}, \"name\": \"Nazar\", \"adress\": \"Kyiv\", \"date\": \"2024-02-05T10:00:00Z\"}", "ns": { "db": "users", "coll": "users" }, "to": null, "documentKey": "{\"_id\": {\"$oid\": \"67a20f0adee77ef71adfe8bc\"}}", "updateDescription": null, "clusterTime": null, "txnNumber": null, "lsid": null }
需求与问题
需要新增identifier字段,将documentKey._id.$oid的值赋给它。但documentKey是JSON字符串而非对象,转成对象后尝试直接用$documentKey._id.$oid提取值时,触发如下报错:
MongoServerError[Location16410]: Invalid $set :: caused by :: FieldPath field names may not start with '$'. Consider using $getField or $setField.
报错原因
MongoDB的字段路径规则不允许以$开头,直接写$documentKey._id.$oid会被当成字段路径解析,而非访问解析后的对象属性,因此必须用$getField操作符来获取带$前缀的字段值。
解决方法
方法一:先转对象再提取
先将字符串类型的documentKey转为对象,再用$getField提取$oid的值:
db.events.aggregate([ { $set: { documentKey: { $cond: { if: { $eq: [{ $type: "$documentKey" }, "string"] }, then: { $function: { body: "function(str) { return JSON.parse(str); }", args: ["$documentKey"], lang: "js" } }, else: "$documentKey" } } } }, { $set: { "identifier": { $getField: { field: "$oid", input: "$documentKey._id" } } } } ]);
方法二:解析时直接提取(更高效)
在$function中解析字符串的同时直接取出$oid值,减少聚合阶段,提升性能:
db.events.aggregate([ { $set: { identifier: { $cond: { if: { $eq: [{ $type: "$documentKey" }, "string"] }, then: { $function: { body: "function(str) { return JSON.parse(str)._id.$oid; }", args: ["$documentKey"], lang: "js" } }, else: { $getField: { field: "$oid", input: "$documentKey._id" } } } } } } ]);
内容的提问来源于stack exchange,提问作者Nazar Mazuryk
相关产品推荐
相关产品推荐

