MongoDB - Update objects in a document's array (nested updating)

后端 未结 3 1511

Assume we have the following collection, which I have few questions about:

{
    \"_id\" : ObjectId(\"4faaba123412d654fe83hg876\"),
    \"user_id\" : 123456         


        
相关标签:
3条回答
  • 2020-11-22 02:13

    There is no way to do this in single query. You have to search the document in first query:

    If document exists:

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

    Else

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

    No need to add condition {$ne : "my_item_two" }.

    Also in multithreaded enviourment you have to be careful that only one thread can execute the second (insert case, if document did not found) at a time, otherwise duplicate embed documents will be inserted.

    0 讨论(0)
  • 2020-11-22 02:20

    For question #1, let's break it into two parts. First, increment any document that has "items.item_name" equal to "my_item_two". For this you'll have to use the positional "$" operator. Something like:

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

    Note that this will only increment the first matched subdocument in any array (so if you have another document in the array with "item_name" equal to "my_item_two", it won't get incremented). But this might be what you want.

    The second part is trickier. We can push a new item to an array without a "my_item_two" as follows:

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

    For your question #2, the answer is easier. To increment the total and the price of item_three in any document that contains "my_item_three," you can use the $inc operator on multiple fields at the same time. Something like:

    db.bar.update( {"items.item_name" : {$ne : "my_item_three" }} ,
                   {$inc : {total : 1 , "items.$.price" : 1}} ,
                   false ,
                   true);
    
    0 讨论(0)
  • 2020-11-22 02:24

    We can use $set operator to update the nested array inside object filed update the value

    db.getCollection('geolocations').update( 
       {
           "_id" : ObjectId("5bd3013ac714ea4959f80115"), 
           "geolocation.country" : "United States of America"
       }, 
       { $set: 
           {
               "geolocation.$.country" : "USA"
           } 
        }, 
       false,
       true
    );
    
    0 讨论(0)
提交回复
热议问题