I have the following collection
{ "_id" : ObjectId("57315ba4846dd82425ca2408"), "myarray" : [ { userId : ObjectId("570ca5e48dbe673802c2d035"), point : 5 }, { userId : ObjectId("613ca5e48dbe673802c2d521"), point : 2 }, ] }
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.
db.collection.update({ _id : ObjectId("57315ba4846dd82425ca2408"), "myarray.userId" : ObjectId("570ca5e48dbe673802c2d035") }, { $set: { "myarray.$.point": 10 } })
But if userId
doesn't exist, nothing happens.
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?
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>] .
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With