首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何更新文档数组中的对象(嵌套更新)

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

Stack Overflow用户
提问于 2012-05-10 02:53:27
回答 4查看 226.8K关注 0票数 228

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

{
    "_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”数组中。

  1. 如何同时更新两个字段?例如,增加"my_item_three“的价格,同时增加”my_item_three“(具有相同的值)。

我更喜欢在Python端这样做,否则我必须在客户端( MongoDB )加载文档,构造更新后的文档,并用MongoDB中的现有文档替换它。

这就是我尝试过的方法,如果对象存在,它工作得很好:

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

但是,如果键不存在,它什么也不做。此外,它只更新嵌套的对象。使用此命令也无法更新"total“字段。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-05-10 04:57:28

对于第一个问题,让我们把它分成两部分。首先,递增任何"items.item_name“等于"my_item_two”的文档。为此,您必须使用位置运算符"$“。类似于:

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

请注意,这只会递增任何数组中第一个匹配的子文档(因此,如果数组中有另一个文档的"item_name“等于"my_item_two",则不会递增)。但这可能是你想要的。

第二部分比较棘手。我们可以将一个新项目推送到一个没有"my_item_two“的数组中,如下所示:

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

对于你的第二个问题,答案更简单。要在任何包含"my_item_three“的文档中增加item_three的总数和价格,可以同时对多个字段使用$inc运算符。类似于:

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

Stack Overflow用户

发布于 2013-08-03 03:22:40

没有办法在单个查询中做到这一点。您必须在第一个查询中搜索文档:

如果文档存在:

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" }

此外,在多线程环境中,您必须注意一次只有一个线程可以执行第二个线程(如果没有找到文档,则插入大小写),否则将插入重复的嵌入文档。

票数 25
EN

Stack Overflow用户

发布于 2020-02-16 03:25:05

我们可以使用$set运算符来更新object字段中的嵌套数组,更新值

db.getCollection('geolocations').update( 
   {
       "_id" : ObjectId("5bd3013ac714ea4959f80115"), 
       "geolocation.country" : "United States of America"
   }, 
   { $set: 
       {
           "geolocation.$.country" : "USA"
       } 
    }, 
   false,
   true
);
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10522347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档