51
{
  "_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,005
  • 5
  • 41
  • 59
徐巧民
  • 513
  • 1
  • 4
  • 5

4 Answers4

92

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" } }
)
chridam
  • 95,056
  • 21
  • 214
  • 219
  • 1
    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 Mar 07 '18 at 17:07
  • @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? – chridam Mar 07 '18 at 17:32
  • I will try a bit more. Maybe is some driver problem with Robo3T and backward compatibility: https://stackoverflow.com/questions/4669178/how-to-update-multiple-array-elements-in-mongodb/46054172#46054172. If nothing works, I will open a question. Thank you! :) – Dherik Mar 07 '18 at 17:44
  • 1
    I'm using MongoDB 3.2.0. Apparently this version not supports this kind of operation. – Dherik Mar 07 '18 at 18:14
6

You can use $set operator.

> db.test.update({"friends.u._id":"eGqDjAjjtYADbuSnn"},{$set:{"friends.$.u.name":"hello"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
styvane
  • 55,207
  • 16
  • 142
  • 150
Srivatsa N
  • 2,243
  • 4
  • 20
  • 36
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.

Sanjay Bharwani
  • 2,151
  • 25
  • 28
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