MongoDB实现BsonDocument数组的条件更新或插入操作
MongoDB 数组元素的条件更新或插入实现
需求说明
- 匹配
pId=123的文档 - 若文档中
gmData.CarData.cars数组存在oid='car_1'的元素,更新该元素的dt字段为指定新值 - 若不存在该oid的元素,则向
gmData.CarData.cars数组插入包含指定dt的新对象
原始数据集
{ "_id" : ObjectId("65a52a03ed163a5b8a06a80d"), "pId" : 123, "fv" : "1.2.3", "gmData" : { "CarData" : { "cars" : [ { "oid" : "car_1", "dt" : { "id" : "car_1", "age" : 123, "add" : "add_1" } }, { "oid" : "car_2", "dt" : { "id" : "car_2", "age" : 234, "add" : "add_2" } }, { "oid" : "car_3", "dt" : { "id" : "car_3", "age" : 345, "add" : "add_3" } } ] } } }
已尝试的仅支持更新的语句
db.test.updateOne( { $and: [{pId:123}, {"gmData.CarData.cars.oid":"car_1"}],}, { "$set":{"gmData.CarData.cars.$[curr].dt":{"id":"car_11","age":1123,"add":"add_11"}} }, { arrayFilters: [ { "curr.oid": { $eq: "car_1" } } ] } )
完整解决方案
利用MongoDB 4.2+支持的聚合管道式更新,通过条件判断实现"存在则更新,不存在则插入"的逻辑:
db.test.updateOne( { pId: 123 }, [ { $set: { "gmData.CarData.cars": { $cond: { if: { $in: ["car_1", "$gmData.CarData.cars.oid"] }, then: { $map: { input: "$gmData.CarData.cars", as: "car", in: { $mergeObjects: [ "$$car", { $cond: { if: { $eq: ["$$car.oid", "car_1"] }, then: { dt: { id: "car_11", age: 1123, add: "add_11" } }, else: {} } } ] } } }, else: { $concatArrays: [ "$gmData.CarData.cars", [{ oid: "car_1", dt: { id: "car_11", age: 1123, add: "add_11" } }] ] } } } } } ] )
代码逻辑说明
- 匹配条件仅保留
pId:123,将数组元素的判断逻辑移至更新管道内 - 外层
$cond通过$in检查数组中是否存在oid='car_1'的元素 - 存在目标元素时:用
$map遍历数组,找到匹配元素后通过$mergeObjects更新其dt字段,其余元素保持原样 - 不存在目标元素时:用
$concatArrays将新元素追加至原数组末尾
内容的提问来源于stack exchange,提问作者AG-Satbir
相关产品推荐
相关产品推荐

