I am trying to find a record in a nested array, modify it, and then project it.
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 record where "cond=4", update it to "upd=55" and return the record.
I've 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 receive the following result:
{
"_id" : ObjectId("56558dfc45a06f51decb4ab7"),
"arr" : [
{},
{},
{},
{},
{}
]
}
*I'm using MongoDB version :3.0.7
You can also try the positional $
operator used with the findAndModify()
method. The operator will identify the element in an array to update without explicitly specifying the position of the element in the array. Note, the array field must appear as part of the query document and to return the document with the modifications made on the update, use the new option, so your update would be like
db.tests.findAndModify({
query: {
"arr.cond": 4
},
update: {
"$set": {"arr.$.upd": 55 }
},
new : true,
fields: { "arr": 1, "_id": 0 }
})
will produce the ouput:
{
"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 the updated document, with projection the positional $ projection
operator can only be used in the projection document of the find()
method or the findOne()
method so the findAndModify()
's field
option will not project that part of the array using the $ projection
operator.
A workaround would be to use the native JavaScript filter()
method on 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);
This will print
[ { "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 } ] }
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