MongoDB project updated the project in a nested array in the query "findAndModify"

I am trying to find a record in a nested array, modify it and then project.

Let's say I have the following collection:

{ "_id" : ObjectId("56558dfc45a06f51decb4ab7"), "arr" : [ { "cond" : 1.0000000000000000, "upd" : 2.0000000000000000 }, { "cond" : 2.0000000000000000, "upd" : 3.0000000000000000 }, { "cond" : 4.0000000000000000, "upd" : 5.0000000000000000 }, { "cond" : 6.0000000000000000, "upd" : 7.0000000000000000 }, { "cond" : 8.0000000000000000, "upd" : 9.0000000000000000 } ] } 

I want to find the entry where "cond = 4", update it to "upd = 55" and return the entry.

I tried the following query:

 db.tests.findAndModify({ query:{ "arr": {"$elemMatch": {"cond":4}} }, update: { "$set": {"arr.$": {"cond": 4, "upd": 55, "new": true}} }, fields: {"arr.$":1} }) 

It performs the update well, but I get the following result:

 { "_id" : ObjectId("56558dfc45a06f51decb4ab7"), "arr" : [ {}, {}, {}, {}, {} ] } 

* I am using MongoDB version: 3.0.7

+5
source share
1 answer

You can also try using the positional $ operator used with findAndModify() . The operator will identify the element in the array for updating without explicitly specifying the position of the element in the array. Please note: the array field should be displayed as part of the request document and return the document with the changes made to the update, use the new parameter, so your update will look like

 db.tests.findAndModify({ query: { "arr.cond": 4 }, update: { "$set": {"arr.$.upd": 55 } }, new : true, fields: { "arr": 1, "_id": 0 } }) 

will produce output:

 { "arr": [ { "cond" : 1, "upd" : 2 }, { "cond" : 2, "upd" : 3 }, { "cond" : 4, "upd" : 55 }, { "cond" : 6, "upd" : 7 }, { "cond" : 8, "upd" : 9 } ] } 

Since you want to return an updated document, the positional $ projection operator in the projection document of the find() or findOne() method can be used with the projection, so findAndModify() field will not project this part of the array using the $ projection operator.

A workaround would be to use your own JavaScript filter() method in the returned arr field as

 var result = db.tests.findAndModify({ query: { "arr.cond": 4 }, update: { "$set": {"arr.$.upd": 55 } }, new : true, fields: { "arr": 1, "_id": 0 } }) var updated = [] if (result && result.arr) updated = result.arr.filter(function (item) { return item.cond == 4; }); printjson(updated); 

Will open

 [ { "cond" : 4, "upd" : 55 } ] 

- UPDATE -

Or the $elemMatch projection, as you suggested in the comments below:

 var result = db.tests.findAndModify({ query: { "arr.cond": 4 }, update: { "$set": {"arr.$.upd": 55 } }, new : true, fields: {"arr": {"$elemMatch": { "cond": 4 } }, "_id": 0 } }) printjson(result); 

Output

 { "arr" : [ { "cond" : 4, "upd" : 55 } ] } 
+2
source

Source: https://habr.com/ru/post/1236794/


All Articles