Update field in exact element array in MongoDB
MongodbMongodb QueryNosqlMongodb Problem Overview
I have a document structured like this:
{
_id:"43434",
heroes : [
{ nickname : "test", items : ["", "", ""] },
{ nickname : "test2", items : ["", "", ""] },
]
}
Can I $set
the second element of the items
array of the embedded object in array heros
with nickname
"test"
?
Result:
{
_id:"43434",
heroes : [
{ nickname : "test", items : ["", "new_value", ""] }, // modified here
{ nickname : "test2", items : ["", "", ""] },
]
}
Mongodb Solutions
Solution 1 - Mongodb
You need to make use of 2 concepts: mongodb's positional operator and simply using the numeric index for the entry you want to update.
The positional operator allows you to use a condition like this:
{"heroes.nickname": "test"}
and then reference the found array entry like so:
{"heroes.$ // <- the dollar represents the first matching array key index
As you want to update the 2nd array entry in "items", and array keys are 0 indexed - that's the key 1.
So:
> db.denis.insert({_id:"43434", heroes : [{ nickname : "test", items : ["", "", ""] }, { nickname : "test2", items : ["", "", ""] }]});
> db.denis.update(
{"heroes.nickname": "test"},
{$set: {
"heroes.$.items.1": "new_value"
}}
)
> db.denis.find()
{
"_id" : "43434",
"heroes" : [
{"nickname" : "test", "items" : ["", "new_value", "" ]},
{"nickname" : "test2", "items" : ["", "", "" ]}
]
}
Solution 2 - Mongodb
Try update document in array using positional $,
The positional $ operator facilitates updates to arrays that contain embedded documents. Use the positional $ operator to access the fields in the embedded documents with the dot notation on the $ operator.
db.collection.update(
{ "heroes.nickname": "test" },
{ $set: { "heroes.$.items.1": "new_value" } },
{ multi: true }
);
Solution 3 - Mongodb
Try update with positional $ and $position,
db.collection.update(
{ heroes:{ $elemMatch:{ "nickname" : "test"} } },
{
$push: {
'heroes.$.items': {
$each: ["new_value" ],
$position: 1
}
}
}
)
Solution 4 - Mongodb
This solution works well. Just want to add one point. Here is the structure. I need to find OrderItemId is 'yyy' and update. If the query field in condition is an array, like below "OrderItems.OrderItemId" is array. You can not use "OrderItems.OrderItemId[0]" as operation in the query. Instead, you need to use "OrderItems.OrderItemId" to compare. Otherwise, it can not match one.
{
_id: 'orderid',
OrderItems: [
{
OrderItemId: ['xxxx'],
... },
{
OrderItemId: ['yyyy'],
...},
]
}
result = await collection.updateOne(
{ _id: orderId, "OrderItems.OrderItemId": [orderItemId] },
{ $set: { "OrderItems.$.imgUrl": imgUrl[0], "OrderItems.$.category": category } },
{ upsert: false },
)
console.log(' (result.modifiedCount) ', result.modifiedCount)
console.log(' (result.matchedCount) ', result.matchedCount)
Solution 5 - Mongodb
go further! Use string template for paste your variable indexes in the way
yourModel.findOneAndUpdate(
{ _id: "43434" },
{
$set: {
[`heroes.${heroesIndex}.items.${itemIndex}`]: "new_value",
},
}
);
or without template
yourModel.findOneAndUpdate(
{ _id: "43434" },
{
$set: {
'heroes.0.items.1': "new_value",
},
}
);