MongoDB - Update or Insert object in array

后端 未结 7 1953
醉话见心
醉话见心 2020-12-08 04:26

I have the following collection

{
    "_id" : ObjectId("57315ba4846dd82425ca2408"),
    "myarray" : [ 
        {
            use         


        
相关标签:
7条回答
  • 2020-12-08 05:24

    I haven't found any solutions based on a one atomic query. Instead there are 3 ways based on a sequence of two queries:

    1. always $pull (to remove the item from array), then $push (to add the updated item to array)

      db.collection.update(
                     { _id : ObjectId("57315ba4846dd82425ca2408")},
                     { $pull: {"myarray.userId": ObjectId("570ca5e48dbe673802c2d035")}}
      )
      
      db.collection.update(
                     { _id : ObjectId("57315ba4846dd82425ca2408")},
                     {
                       $push: {
                                "myarray": {
                                            userId:ObjectId("570ca5e48dbe673802c2d035"),
                                            point: 10
                                           }
                               }
                      }
      )
      
    2. try to $set (to update the item in array if exists), then get the result and check if the updating operation successed or if a $push needs (to insert the item)

      var result = db.collection.update(
          {
             _id : ObjectId("57315ba4846dd82425ca2408"),
            "myarray.userId": ObjectId("570ca5e48dbe673802c2d035")
          },
          {
             $set: {"myarray.$.point": {point: 10}}
          }
       );
      
      if(!result.nMatched){
             db.collection.update({_id: ObjectId("57315ba4846dd82425ca2408")},
                                  {
                                    $addToSet: {
                                                 myarray: {
                                                    userId: ObjectId("570ca5e48dbe673802c2d035"),
                                                    point: 10
                                                }
                                  }
             );
      
    3. always $addToSet (to add the item if not exists), then always $set to update the item in array

         db.collection.update({_id: ObjectId("57315ba4846dd82425ca2408")},
                               myarray: { $not: { $elemMatch: {userId: ObjectId("570ca5e48dbe673802c2d035")} } } },
                              { 
                                 $addToSet : {
                                               myarray: {
                                                          userId: ObjectId("570ca5e48dbe673802c2d035"),
                                                          point: 10
                                                         }
                                              }
                               },
                              { multi: false, upsert: false});
      
         db.collection.update({
                                _id: ObjectId("57315ba4846dd82425ca2408"),
                                 "myArray.userId": ObjectId("570ca5e48dbe673802c2d035")
                              },
                              { $set : { myArray.$.point: 10 } },
                              { multi: false, upsert: false});
      

    1st and 2nd way are unsafe, so transaction must be established to avoid two concurrent requests could push the same item generating a duplicate.

    3rd way is safer. the $addToSet adds only if the item doesn't exist, otherwise nothing happens. In case of two concurrent requests, only one of them adds the missing item to the array.

    0 讨论(0)
提交回复
热议问题