Reputation: 731
I am working with MongoDB in one of my project. For the next feature I need to add a flag to array of objects by looping with a matching condition.
Following is an example of document that I have -
{
"_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
"colors" : [
{ "status" : "done" },
{ "status" : "done" },
{ "status" : "n/a" }
]
}
Output should be -
{
"_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
"colors" : [
{
"status" : "done",
"is_in_production" : true
},
{
"status" : "done",
"is_in_production" : true
},
{
"status" : "n/a"
}
]
}
I used the following query -
db.getCollection('products').update(
{
"colors.status": {
"$in":[
"done"
]
}
},
{$set: { 'colors.$[].is_in_production' :true }},
{multi: true}
)
That resulted the following error -
cannot use the part(colors of colors.$[].is_in_production)totraversetheelement({ colors: [{ "status" : "done" }, { "status" : "done" }, { "status" : "n/a" }] )}
Can someone help me with the query?? Thanks in Advance
Upvotes: 3
Views: 7122
Reputation: 5476
Use updateMany together with arrayFilters to update multiple documents in an array
db.products.updateMany(
{ "colors.status": "done" },
{ $set: { "colors.$[element].is_in_production" : true}},
{ arrayFilters: [{"element.status" : "done"}]}
)
Upvotes: 2
Reputation: 3459
Use arrayFilters
to update only a subset of embedded documents.
Try this query:
db.products.update(
{
"colors.status": {
"$in":[
"done"
]
}
},
{$set: { 'colors.$[element].is_in_production' :true }},
{multi: true, arrayFilters:[{"element.status":"done"}]}
)
Output is:
/* 1 */
{
"_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
"colors" : [
{
"status" : "done",
"is_in_production" : true
},
{
"status" : "done",
"is_in_production" : true
},
{
"status" : "n/a"
}
]
}
Note that you need MongoDB 3.6 and need to execute on latest shell (no third party tools preferably) in order for the arrayFilters
to work properly.
If the above query isn't working for your Mongo version, try this query:
db.sample.findAndModify({
query:{
"colors.status": {
"$in":[
"done"
]
}
},
update:{$set: { 'colors.$[element].is_in_production' : true }},
multi: true,
arrayFilters:[{"element.status":"done"}]
})
Upvotes: 1