Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB - Update or Insert object in array

Tags:

mongodb

I have the following collection

{     "_id" : ObjectId("57315ba4846dd82425ca2408"),     "myarray" : [          {             userId : ObjectId("570ca5e48dbe673802c2d035"),             point : 5         },         {             userId : ObjectId("613ca5e48dbe673802c2d521"),             point : 2         },              ] } 

These are my questions

I want to push into myarray if userId doesn't exist, it should be appended to myarray. If userId exists, it should be updated to point.

I found this

db.collection.update({     _id : ObjectId("57315ba4846dd82425ca2408"),     "myarray.userId" :  ObjectId("570ca5e48dbe673802c2d035") }, {     $set: { "myarray.$.point": 10 } }) 

But if userId doesn't exist, nothing happens.

and

db.collection.update({     _id : ObjectId("57315ba4846dd82425ca2408") }, {   $push: {       "myarray": {           userId: ObjectId("570ca5e48dbe673802c2d035"),           point: 10       }   } }) 

But if userId object already exists, it will push again.

What is the best way to do this in MongoDB?

like image 341
Narupon Tee Srisantitham Avatar asked May 25 '16 04:05

Narupon Tee Srisantitham


People also ask

How do you update data in an array of objects in MongoDB?

To project, or return, an array element from a read operation, see the $ projection operator instead. To update all elements in an array, see the all positional operator $[] instead. To update all elements that match an array filter condition or conditions, see the filtered positional operator instead $[<identifier>] .

How do I add an object to an array in MongoDB?

In MongoDB, the $push operator is used to appends a specified value to an array. If the mentioned field is absent in the document to update, the $push operator add it as a new field and includes mentioned value as its element. If the updating field is not an array type field the operation failed.

How do I change the nested array element in MongoDB?

Update Nested Arrays in Conjunction with $[]The $[<identifier>] filtered positional operator, in conjunction with the $[] all positional operator, can be used to update nested arrays. The following updates the values that are greater than or equal to 8 in the nested grades. questions array if the associated grades.


Video Answer


2 Answers

Try this

db.collection.update(     { _id : ObjectId("57315ba4846dd82425ca2408")},     { $pull: {"myarray.userId": ObjectId("570ca5e48dbe673802c2d035")}} ) db.collection.update(     { _id : ObjectId("57315ba4846dd82425ca2408")},     { $push: {"myarray": {         userId:ObjectId("570ca5e48dbe673802c2d035"),         point: 10     }} ) 

Explination: in the first statment $pull removes the element with userId= ObjectId("570ca5e48dbe673802c2d035") from the array on the document where _id = ObjectId("57315ba4846dd82425ca2408")

In the second one $push inserts this object { userId:ObjectId("570ca5e48dbe673802c2d035"), point: 10 } in the same array.

like image 159
Flying Fisher Avatar answered Oct 02 '22 23:10

Flying Fisher


The accepted answer by Flying Fisher is that the existing record will first be deleted, and then it will be pushed again.

A safer approach (common sense) would be to try to update the record first, and if that did not find a match, insert it, like so:

// first try to overwrite existing value var result = db.collection.update(    {        _id : ObjectId("57315ba4846dd82425ca2408"),        "myarray.userId": ObjectId("570ca5e48dbe673802c2d035")    },    {        $set: {"myarray.$.point": {point: 10}}    } ); // you probably need to modify the following if-statement to some async callback // checking depending on your server-side code and mongodb-driver if(!result.nMatched) {     // record not found, so create a new entry     // this can be done using $addToSet:     db.collection.update(         {             _id: ObjectId("57315ba4846dd82425ca2408")         },         {             $addToSet: {                 myarray: {                     userId: ObjectId("570ca5e48dbe673802c2d035"),                     point: 10                 }             }         }     );     // OR (the equivalent) using $push:     db.collection.update(         {             _id: ObjectId("57315ba4846dd82425ca2408"),             "myarray.userId": {$ne: ObjectId("570ca5e48dbe673802c2d035"}}         },         {             $push: {                 myarray: {                     userId: ObjectId("570ca5e48dbe673802c2d035"),                     point: 10                 }             }         }     ); } 

This should also give (common sense, untested) an increase in performance, if in most cases the record already exists, only the first query will be executed.

like image 44
Yeti Avatar answered Oct 02 '22 22:10

Yeti