Reputation: 593
{
"_id": "xPBc4By8FemDwTPqH",
"u": {
"_id": "6PoZawHZcQz4Gwzcv",
"username": "michael"
},
"friends": [
{
"u": {
"_id": "eGqDjAjjtYADbuSnn",
"username": "michael",
"name": "michael"
}
},
{
"u": {
"_id": "k4gKCGwYryXDMMHvs",
"username": "joyce",
"name": "joyce"
}
}
]
}
I want to update the name of "friends.u.username": "michael" 's name is "hello", how I need to do it.
Upvotes: 59
Views: 84995
Reputation: 103305
Apply the $set
operator together with the $
positional operator in your update to change the name
field.
The $
positional operator will identify the correct element in the array to update without explicitly specifying the position of the element in the array, thus your final update statement should look like:
db.collection.update(
{ "friends.u.username": "michael" },
{ "$set": { "friends.$.u.name": "hello" } }
)
To update multiple elements in an array when more than one element matches the filter, you can use the $\[<identifier>\]
syntax with the arrayFilters
option. The following will update all matching elements in the "friends" array:
db.collection.update(
{ "friends.u.username": "michael" },
{ "$set": { "friends.$[elem].u.name": "hello" } },
{
"arrayFilters": [{ "elem.u.username": "michael" }],
"multi": true
}
)
The $[elem]
syntax identifies array elements that match the specified filter in the arrayFilters
option. The multi: true
option is added to update all matching documents instead of just the first one.
Upvotes: 113
Reputation: 161
If you are using python, I created this function to generate the new update:
def generate_set_to_update_document(field: str, changes: dict) -> dict:
new_set = {}
for change in changes.keys():
new_set[f"{field}.$.{change}"] = changes[change]
return new_set
Upvotes: 0
Reputation: 4739
Below should work fine as its tested
First check the current value of the array.
db.test.findOne({"friends.u.id" : "eGqDjAjjtYADbuSnn"},{"friends.u.name":1})
Now fire the update command
db.test.update({"friends.u.id" : "eGqDjAjjtYADbuSnn"},{$set:{"friends.$.u.name":"hello"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Now check the results again to validate the update values
db.test.findOne({"friends.u.id" : "eGqDjAjjtYADbuSnn"},{"friends.u.name":1})
Hope this helps.
Upvotes: 0
Reputation: 2321
You can use $set operator.
> db.test.update({"friends.u._id":"eGqDjAjjtYADbuSnn"},{$set:{"friends.$.u.name":"hello"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Upvotes: 8