MongoDB嵌套数组更新效率:聚合管道vs多次查询方案对比
问题:MongoDB嵌套数组的高效更新方案
我有一个包含嵌套对象数组的MongoDB文档,结构简化如下:
{ "username": "user", "listOne": [ { "name": "foo", "qnty": 5 }, { "name": "bar", "qnty": 3 } ], "listTwo": [ { "id": 1, "qnty": 13 }, { "id": 2, "qnty": 9 } ] }
我需要根据标识符更新数组中的qnty字段。针对listOne,我原本的做法是:
db.collection.findOneAndUpdate( { "username": "user", "listOne.name": name }, { $inc: { "listOne.$.qnty": qntyChange, } } )
当查询未找到对应name的对象时,再执行一次$push操作。由于这种情况较少,两次查询的成本可接受。
但新增listTwo后,若沿用原策略,最坏情况下需执行四次数据库查询。为避免多次查询,我编写了基于聚合管道的更新操作,逻辑如下:
- 检查目标数组中是否存在对应标识符的对象;
- 若存在,遍历数组:匹配标识符则更新
qnty,否则返回原对象; - 若不存在,向数组中添加新对象;
- 对
listOne和listTwo重复上述逻辑。
listOne对应的聚合管道代码如下:
db.coll1.updateOne( { "username": "user" }, [{ "$set": { "listOne": { "$cond": { "if": { "$in": [ name, "$listOne.name" ] }, "then": { "$map": { "input": "$listOne", "as": "one", "in": { "$cond": { "if": { "$eq": [ "$$one.name", name ] }, "then": { "$mergeObjects": [ "$$one", { "qnty": { "$add": [ "$$one.qnty", qntyChange ] } } ] }, "else": "$$one" } } } }, "else": { "$concatArrays": [ "$listOne", [ { "name": name, "qnty": qntyChange } ] ] } } } } }] );
我现在的疑问是该聚合管道方案的效率如何:由于需按服务器时间付费,希望采用高效方案。集合将包含数千条文档,而每个数组最多千余元素,但该管道似乎会遍历数组两次。更担心的是,使用$map时,未匹配的对象是否会被重写?这会增加服务器耗时及写入字节数,进而提升成本。请问是否有更优的解决方案?
内容的提问来源于stack exchange,提问作者Arthur Pereira
相关产品推荐
相关产品推荐

