如何更新文档数组中的对象(嵌套更新)

7 浏览
0 Comments

如何更新文档数组中的对象(嵌套更新)

假设我们有以下集合,我有几个问题想问:

{
    "_id" : ObjectId("4faaba123412d654fe83hg876"),
    "user_id" : 123456,
    "total" : 100,
    "items" : [
            {
                    "item_name" : "my_item_one",
                    "price" : 20
            },
            {
                    "item_name" : "my_item_two",
                    "price" : 50
            },
            {
                    "item_name" : "my_item_three",
                    "price" : 30
            }
    ]
}

  1. 我想增加 \"item_name\":\"my_item_two\" 的价格,如果不存在,则将其附加到 \"items\" 数组中。
  2. 如何同时更新两个字段?例如,增加 \"my_item_three\" 的价格,并同时增加 \"total\"(具有相同的值)。

我更喜欢在 MongoDB 方面解决这个问题,否则我必须在客户端(Python)中加载文档并构造更新后的文档,然后将其替换为 MongoDB 中现有的文档。

如果对象存在,这是我尝试过并且正常工作的内容:

db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})

但是,如果该键不存在,则不执行任何操作。此外,它仅更新嵌套对象。在此命令中没有办法同时更新 \"total\" 字段。

admin 更改状态以发布 2023年5月23日
0
0 Comments

没有办法在单个查询中完成此操作。您必须在第一个查询中搜索文档:

如果文档存在:

db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } , 
                {$inc : {"items.$.price" : 1} } , 
                false , 
                true);

否则:

db.bar.update( {user_id : 123456 } , 
                {$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
                false , 
                true);

不需要添加条件{$ne : "my_item_two" }

此外,在多线程环境中,您必须小心,只有一个线程可以同时执行第二个操作(如果未找到文档,则插入操作),否则会插入重复的嵌套文档。

0
0 Comments

\n\n对于问题#1,让我们将其分成两部分。首先,将具有“items.item_name”等于“my_item_two”的任何文档增加。为此,您将必须使用位置“$”运算符。类似于:\n\n

 db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } , 
                {$inc : {"items.$.price" : 1} } , 
                false , 
                true);

\n\n请注意,这将仅增加任何数组中的第一个匹配的子文档(因此,如果数组中有另一个“item_name”等于“my_item_two”的文档,则不会增加)。但这可能是您想要的。\n\n第二部分要复杂得多。我们可以如下方式向没有“my_item_two”的数组推送新项目:\n\n

 db.bar.update( {user_id : 123456, "items.item_name" : {$ne : "my_item_two" }} , 
                {$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
                false , 
                true);

\n\n对于您的问题#2,答案更容易。要增加包含“my_item_three”的任何文档中item_three的总数和价格,可以同时对多个字段使用$inc运算符。类似于:\n\n

db.bar.update( {"items.item_name" : {$ne : "my_item_three" }} ,
               {$inc : {total : 1 , "items.$.price" : 1}} ,
               false ,
               true);

0