60
{
 "_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.

ButterDog
5,2556 gold badges47 silver badges63 bronze badges
asked Dec 23, 2015 at 8:24
0

4 Answers 4

115

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.

answered Dec 23, 2015 at 8:35
Sign up to request clarification or add additional context in comments.

7 Comments

For some reason is not working for me... Nothing happen, but If I use 0 instead of $, the (wrong) element on array is changed
@Dherik Do you have a question already with the details for your problem? If not can you create one with a sample document and your desired result?
I'm using MongoDB 3.2.0. Apparently this version not supports this kind of operation.
For me this only modified a single element. If more than one element matched, only the first will be updated
indeed this only updates first matching nested element. don't know how to allow for multiple matches (updates)
|
8

You can use $set operator.

> db.test.update({"friends.u._id":"eGqDjAjjtYADbuSnn"},{$set:{"friends.$.u.name":"hello"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Sede
61.5k20 gold badges159 silver badges162 bronze badges
answered Dec 23, 2015 at 8:39

Comments

0

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.

answered Sep 16, 2019 at 8:23

Comments

0

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
answered Aug 10, 2021 at 23:05

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.