MongoDB位置操作符$未正确更新数组值,反而新增元素问题
解决MongoDB同时更新两个数组时$占位符导致的数组新增问题
需求是用$inc操作符同时更新MongoDB文档中两个数组的指定字段:
- 对
pricing数组中default为true的对象,增量更新qty和total字段 - 对
quantity数组中指定_id的对象,增量更新qty字段
但执行以下代码后,pricing数组没有更新原有对象,反而新增了一条条目。
现有文档结构
{ _id: ObjectId("***********"), quantity: [ { "storage": "GODOWN", "qty": 1, "_id": "666e0f15876d5be1a8ce0a04" }, { "storage": "SHOP", "qty": 0, "_id": "666e0f15876d5be1a8ce0a05" }, { "storage": "GODOWN 2", "qty": 0, "_id": "666e0f15876d5be1a8ce0a06" } ], pricing: [{ "firstAddedDate": "06/16/2024", "mrp": 0, "price": 0, "qty": 1, "total": 80, "default": true, "_id": "666e0f15876d5be1a8ce0a03" }] }
原执行代码
defualtPricingUpdated = await Item.findOneAndUpdate( { _id: newEntry.itemID, "pricing.default": true, "quantity._id": newEntry.storageID }, { $inc: { "pricing.$.qty": Number(newEntry.qty), "quantity.$.qty": newEntry.qty, "pricing.$.total": newEntry.amount }}, { returnDocument: "after" } ).session(session)
问题原因
MongoDB的$占位符在单个更新操作中只能匹配第一个匹配到的数组元素,当你同时在两个数组上使用$时,它无法区分要指向哪个数组的匹配项,导致更新逻辑混乱,最终出现意外新增数组元素的情况。
解决方案:使用数组过滤操作符
通过定义数组过滤器(Array Filters),给每个数组的匹配条件分配独立标识符,实现精准定位两个数组的目标元素。
修改后的代码:
defualtPricingUpdated = await Item.findOneAndUpdate( { _id: newEntry.itemID, "pricing.default": true, "quantity._id": newEntry.storageID }, { $inc: { "pricing.$[pricingFilter].qty": Number(newEntry.qty), "quantity.$[quantityFilter].qty": newEntry.qty, "pricing.$[pricingFilter].total": newEntry.amount } }, { returnDocument: "after", arrayFilters: [ { "pricingFilter.default": true }, { "quantityFilter._id": newEntry.storageID } ] } ).session(session)
代码说明
- 数组过滤器定义:在
arrayFilters中定义两个过滤规则:pricingFilter匹配pricing数组中default: true的元素quantityFilter匹配quantity数组中_id等于指定值的元素
- 精准更新:更新语句中用
$[pricingFilter]和$[quantityFilter]分别指向两个数组的目标元素,彻底避免$占位符的歧义问题 - 条件一致性:查询条件和数组过滤条件保持一致,确保只更新符合要求的文档和数组元素
内容的提问来源于stack exchange,提问作者Sanam
相关产品推荐
相关产品推荐

