If you are using MongoDB 3.0 or later, you need to use .findOneAndUpdate()
and use the projection
option to specify a subset of the field to return. You also need to set returnNewDocument
to true
. Of course, you need to use the $elemMatch
design $elemMatch
because you cannot use positional projection and return a new document.
As someone remarked:
You should use .findOneAndUpdate()
because .findAndModify()
highly regarded as deprecated in every official driver. Another thing is that the syntax and parameters are pretty consistent between the drivers for .findOneAndUpdate()
. With .findAndModify()
most drivers do not use the same single object with request / update / field keys. So this is a bit confusing when someone turns to another language to be consistent. The standard API changes for .findOneAndUpdate()
actually correspond to the server version 3.x, not 3.2.x. The complete difference is that the shell methods actually lagged behind other drivers (by one time!) When implementing the method. Thus, most drivers actually had a large release corresponding to 3.x 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 } )
Starting with MongoDB 3.0, you need to use findAndModify
and the fields
option also you need to set new
to true
in another 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 give:
{ "_id" : ObjectId("56d6a7292c06e85687f44541"), "rankings" : [ { "_id" : ObjectId("46d6a7292c06e85687f55543"), "name" : "Ranking 2", "score" : 11 } ] }
source share