MongoDB两层嵌套数组文档的条件式更新实现求助
问题需求
仅在满足以下三个条件时,将匹配的spotsAvailable字段替换为{ userId: ObjectId(), name: "wendy" }:
- 文档
_id=636c2c6dcb82e7ae6aac0960 weights.weight= 0weights.spotsAvailable.userId= "empty"
示例文档
{ "_id": { "$oid": "636c2c6dcb82e7ae6aac0960" }, "name": "onmygowd", "createdBy": { "$oid": "636c1778f1d09191074f9690" }, "description": "It's gonnam be a good one", "date": { "$date": { "$numberLong": "1667913330000" } }, "location": { "type": "Point", "coordinates": [ 0, 0 ] }, "weights": [ { "spotsAvailable": [ { "name": "empty", "userId": "empty" }, { "name": "John", "userId": { "$oid": "636c1778f1d09191074f9690" } } ], "weight": 0 }, { "spotsAvailable": [ { "name": "empty", "userId": "empty" }, { "name": "John", "userId": { "$oid": "636c1778f1d09191074f9690" } } ], "weight": 123 } ], "eventApplicants": [ { "userId": { "$oid": "636c1778f1d09191074f9690" }, "name": "wallace", "weight": 123.1 } ] }
失败的尝试
1
db.events.updateOne({ _id: ObjectId('636c2c6dcb82e7ae6aac0960'), "weights.weight": 0 }, { $set: { "weights.spotsAvailable.$[el2]": { "name": "George", "userId": ObjectId('636c1778f1d09191074f9690') } } }, { arrayFilters: [{"el2.userId": "empty"}] })
**2** ```javascript db.events.updateOne(db.events.findOne({_id: ObjectId('636c2c6dcb82e7ae6aac0960'), "weights.weight": 0, "weights.spotsAvailable.userId": "empty"}, {$set: {"weights.$[el].spotsAvailable": {"name": "George", "userId": ObjectId('636c1778f1d09191074f9690')}}}, {arrayFilters:[{"el.spotsAvailable.userId": "empty"}] }) ```
**3** ```javascript db.events.updateOne({ _id: ObjectId('636c2c6dcb82e7ae6aac0960'), "weights.weight": 0 }, { $set: { "weights.$[el].spotsAvailable.$[el2]": { "name": "George", "userId": ObjectId('636c1778f1d09191074f9690') } } }, { arrayFilters: [{"el.el2.userId": "empty"}] }) ```
正确实现方法
你的三次尝试存在以下问题:
- 第一次未定位到
weights数组中weight=0的具体元素,直接操作weights.spotsAvailable导致路径错误。 - 第二次错误将
db.events.findOne()作为updateOne的查询参数,updateOne第一个参数必须是查询文档而非查询结果。 - 第三次
arrayFilters条件写法错误,el.el2.userId不是正确的嵌套数组过滤语法,需为两个数组过滤器指定独立匹配条件。
正确的更新语句如下:
db.events.updateOne( { _id: ObjectId('636c2c6dcb82e7ae6aac0960'), "weights.weight": 0 }, { $set: { "weights.$[weightEl].spotsAvailable.$[spotEl]": { "userId": ObjectId(), "name": "wendy" } } }, { arrayFilters: [ { "weightEl.weight": 0 }, { "spotEl.userId": "empty" } ] } )
代码解释
- 查询条件:匹配指定
_id的文档,且文档weights数组存在weight=0的元素。 - $set操作:通过
$[weightEl]定位weights数组中符合条件的元素,再用$[spotEl]定位该元素下spotsAvailable数组中匹配的子元素,完成替换。 - arrayFilters:
{ "weightEl.weight": 0 }:筛选weights数组中weight等于0的元素,对应路径中的$[weightEl]。{ "spotEl.userId": "empty" }:筛选spotsAvailable数组中userId为"empty"的元素,对应路径中的$[spotEl]。
内容的提问来源于stack exchange,提问作者Wayne
相关产品推荐
相关产品推荐

