How to get back the new value after an update in a embedded array?
Solution 1:
If you are on MongoDB 3.0 or newer, you need to use the .findOneAndUpdate()
and use projection
option to specify the subset of fields to return. You also need to set returnNewDocument
to true
. Of course you need to use the $elemMatch
projection operator here because you cannot use a positional projection and return the new document.
As someone pointed out:
You should be using
.findOneAndUpdate()
because.findAndModify()
is highlighed as deprecated in every official language driver. The other thing is that the syntax and options are pretty consistent across drivers for.findOneAndUpdate()
. With.findAndModify()
, most drivers don't use the same single object with "query/update/fields" keys. So it's a bit less confusing when someone applies to another language to be consistent. Standardized API changes for.findOneAndUpdate()
actually correspond to server release 3.x rather than 3.2.x. The full distinction being that the shell methods actually lagged behind the other drivers ( for once ! ) in implementing the method. So most drivers actually had a major release bump corresponding with the 3.x release with such changes.
db.collection.findOneAndUpdate(
{
"_id": ObjectId("56d6a7292c06e85687f44541"),
"rankings._id" : ObjectId("46d6a7292c06e85687f55543")
},
{ $inc : { "rankings.$.score" : 1 } },
{
"projection": {
"rankings": {
"$elemMatch": { "_id" : ObjectId("46d6a7292c06e85687f55543") }
}
},
"returnNewDocument": true
}
)
From MongoDB 3.0 onwards, you need to use findAndModify
and the fields
options also you need to set new
to true
in other to return the new value.
db.collection.findAndModify({
query: {
"_id": ObjectId("56d6a7292c06e85687f44541"),
"rankings._id" : ObjectId("46d6a7292c06e85687f55543")
},
update: { $inc : { "rankings.$.score" : 1 } },
new: true,
fields: {
"rankings": {
"$elemMatch": { "_id" : ObjectId("46d6a7292c06e85687f55543") }
}
}
})
Both queries yield:
{
"_id" : ObjectId("56d6a7292c06e85687f44541"),
"rankings" : [
{
"_id" : ObjectId("46d6a7292c06e85687f55543"),
"name" : "Ranking 2",
"score" : 11
}
]
}