web-dev-qa-db-fra.com

MongoDB met à jour les données dans un champ imbriqué

j'utilise Mongo pour être ma base de données. j'ai des données:

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

maintenant, je veux motiver le courrier électronique des amis des utilisateurs, dont le _id est '123' j'écris comme ceci:

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

c'est facile, mais c'est faux, lorsque le tableau des e-mails contient deux données ou plus. donc, ma question est: comment puis-je motiver les données dans un fichier imbriqué --- juste avoir deux ou plusieurs tableaux imbriqués? Merci.

42
allen wang

Vous devez utiliser la Notation des points pour les tableaux.

Autrement dit, vous devez remplacer le $ avec l'index de base zéro de l'élément que vous essayez de mettre à jour.

Par exemple:

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

mettra à jour le premier e-mail du premier ami, et

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

mettra à jour le deuxième e-mail du premier ami.

71
Cristian Lupascu

Solution utilisant 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");
          }
        }

    }
1
Kacper

mettre à jour quelque chose dans un arry à plusieurs niveaux est vraiment une douleur dans le cul, ma façon de le faire: remplacer le arry au niveau profond.

db.user.findOne({_id:'123'},{friends:1}).lean().exec(function(err,user){
   var whichArrayToUpdate;
   for (var ii = 0; ii < user.friends.length; ii++) {
        for (var jj = 0; i < user.friends[ii].emails; jj++) {
            if(user.friends[ii].emails[jj].email == '1111' ){// update it below

                user.friends[ii].emails[jj].email == 'what ever you want to set to.';

                whichArrayToReplace = user.friends[ii].emails;
                break;
            }
        };
   };

   db.user.update({'friends.name':'allen'},{$set{'friends.$.email': whichArrayToReplace} })
})

mais, pourquoi ne pas utiliser la méthode save ()? le save () remplacera tout votre document, si votre document est petit c'est ok, mais si votre document est très gros, c'est une meilleure idée de remplacer juste une partie de votre document.

ou faites la boucle, utilisez la position du tableau de niveau supérieur et du tableau de deuxième niveau (ii et jj) pour mettre à jour.

mon conseil est le suivant: lorsque vous concevez un schéma, ne placez pas de tableau dans un autre tableau à moins que vous ne fassiez aucune mise à jour pour ce tableau.

1
Eisneim