How to get back the new value after an update in a embedded array?

匿名 (未验证) 提交于 2019-12-03 03:09:01

问题:

Given the following MongoDB collection:

{     "_id": ObjectId("56d6a7292c06e85687f44541"),     "name": "My ranking list",     "rankings": [         {             "_id": ObjectId("46d6a7292c06e85687f55542"),             "name": "Ranking 1",             "score": 1         },         {             "_id": ObjectId("46d6a7292c06e85687f55543"),             "name": "Ranking 2",             "score": 10         },         {             "_id": ObjectId("46d6a7292c06e85687f55544"),             "name": "Ranking 3",             "score": 15         },     ] } 

Here is how I increase the score of a given ranking:

db.collection.update(     { "_id": ObjectId("56d6a7292c06e85687f44541"), "rankings._id" : ObjectId("46d6a7292c06e85687f55543") },     { $inc : { "rankings.$.score" : 1 } } ); 

How do I get the new score value? In the previous query I increase the second ranking from 10 to 11... How do I get this new value back after the update?

回答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                 }         ] } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!