MongoDB update data in nested field

You need to use the Dot Notation for the arrays.

That is, you should replace the $ with the zero-based index of the element you're trying to update.

For example:

db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.0.email" : '2222'} });

will update the first email of the first friend, and

db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.1.email" : '2222'} })

will update the second email of the first friend.


One flexible way to do updates to a multilevel array is to use arrayFilters which allows for indexes to be queried for and assigned to an identifier.

db.collection.update(
   { <query selector> },
   { <update operator>: { "array.$[<identifier>].field" : value } },
   { arrayFilters: [ { <identifier>: <condition> } } ] }
)

Here's the example you provided plus a new friend with two emails:

{
   _id : '123'
   friends: [
     {name: 'allen', emails: [
        {email: '11111', using: 'true'}
     ]},
     {name: 'lucy' , emails: [
        {email: '[email protected]', using:'true'}, 
        {email:'[email protected]', using : 'false'}
     ]}
   ]
 }

Suppose [email protected] is being updated to [email protected]. We can use the name and email fields in an array filter to identify the index we want to update.

db.users.update({_id:123}, {$set:{
    "friends.$[updateFriend].emails.$[updateEmail].email : "[email protected]"
}}, {
    "arrayFilters": [
      {"updateFriend.name" : "lucy"},
      {"updateEmail.email" : "[email protected]"}
    ]
})

In this way our update is not sensitive to a particular array order. Also while emails are likely unique I would recommend including a unique id on all subdocuments so the arrayFilters can be exact.


Solution using Mongoose:

    Users.findById("123", function(err, user) {

      var friends = user.friends;
        for ( i=0; i < friends.length; i++ ) {
          if (friends[i].name == 'allen') {
            friends[i].email = '2222';

            user.save(function(err) {
              if (err) throw err;
              console.log("email updated");
            });
          } else {
            console.log("no friends named allen");
          }
        }

    }

Tags:

Nested

Mongodb