Facing issue while trying to update an element within an array of sub document in Mongo. If I consider the following document in the collection "resource"
{
"_id": 1,
"resources": [
{
"resource_id": 1,
"resource_list": ["item1","item2"]
},
{
"resource_id": 2,
"resource_list": ["item4","item3"]
}
]
}
I want to update "item4"
with some other value like "item5"
for "resource_id" = 2
The following statement gave me an error : Cannot apply the positional operator without a corresponding query field containing an array.
db.resource.update({"resources.resource_id": 2, "resources.resource_list": "item4"}, {$set: {"resources.$.resource_list.$": "item5"}})
Any help on this will be highly appreciated.
The positional operator can be used only once in a query. This is a limitation, there is an open ticket for improvement: https://jira.mongodb.org/browse/SERVER-831
An other way to solve this problem could be to push "item5" to the array and pull "item4". Something like this:
db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $pull: { "resources.$.resource_list": "item4" }, $push: { "resources.$.resource_list": "item5" } })
However this isn't possible either, $pull
and $push
can't be used in the same query for the same field. Related ticket: https://jira.mongodb.org/browse/SERVER-1050
I see two solutions. One is to execute two queries. In the first query, you push "item5", in the second query you pull "item4":
db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $push: { "resources.$.resource_list": "item5" } });
db.resource.update({ "resources.resource_id": 2, "resources.resource_list": "item4" }, { $pull: { "resources.$.resource_list": "item4" } });
If you want to do it in one query, you can use mongo shell. Something like this:
db.resource.find({ 'resources.resource_id': 2, 'resources.resource_list': 'item4' }).forEach( function(document) {
for (var i in document.resources) {
if (document.resources[i].resource_id == 2) {
var index = document.resources[i].resource_list.indexOf('item4');
document.resources[i].resource_list[index] = 'item5';
db.resource.save(document);
}
}
})