245 votes

Comment mettre partiellement à jour un objet dans MongoDB afin que le nouvel objet se superpose/fusionne avec l'objet existant ?

Étant donné ce document enregistré dans MongoDB

{
   _id : ...,
   some_key: { 
        param1 : "val1",
        param2 : "val2",
        param3 : "val3"
   }
}

Un objet contenant de nouvelles informations sur param2 y param3 du monde extérieur doit être sauvé

var new_info = {
    param2 : "val2_new",
    param3 : "val3_new"
};

Je veux fusionner / superposer les nouveaux champs sur l'état existant de l'objet afin que le paramètre 1 ne soit pas supprimé.

Faire cela

db.collection.update(  { _id:...} , { $set: { some_key : new_info  } } 

MongoDB fait exactement ce qu'on lui a demandé, et définit some_key à cette valeur. en remplaçant l'ancienne.

{
   _id : ...,
   some_key: { 
      param2 : "val2_new",
      param3 : "val3_new"
   }
}

Quel est le moyen de faire en sorte que MongoDB mette à jour uniquement les nouveaux champs (sans les déclarer un par un explicitement) ? pour obtenir ceci :

{
   _id : ...,
   some_key: { 
        param1 : "val1",
        param2 : "val2_new",
        param3 : "val3_new"
   }
}

J'utilise le client Java, mais tout exemple sera apprécié.

2voto

Patrick Tescher Points 1815

On dirait que tu peux mettre isPartialObject qui pourrait accomplir ce que vous voulez.

2voto

nguyenthang338 Points 37
db.collection.update(  { _id:...} , { $set: { some_key : new_info  } } 

à

db.collection.update( { _id: ..} , { $set: { some_key: { param1: newValue} } } ); 

J'espère que cela vous aidera !

2voto

Guihgo Points 562

Vous devez utiliser les documents incorporés (stringfy l'objet de chemin)

let update = {}
Object.getOwnPropertyNames(new_info).forEach(param => {
   update['some_key.' + param] = new_info[param]
})

Et donc, en JavaScript, vous pouvez utiliser l'opérateur d'étalement (...) pour mettre à jour

db.collection.update(  { _id:...} , { $set: { ...update  } }

1voto

Ashwin Shankar Points 71

Oui, le meilleur moyen est de convertir la notation des objets en une représentation plate de type chaîne de caractères clé-valeur, comme mentionné dans ce commentaire : https://stackoverflow.com/a/39357531/2529199

Je voulais mettre en avant une méthode alternative utilisant cette bibliothèque NPM : https://www.npmjs.com/package/dot-object qui vous permet de manipuler différents objets en utilisant la notation par points.

J'ai utilisé ce modèle pour créer de manière programmatique une propriété d'objet imbriquée en acceptant la valeur-clé comme une variable de fonction, comme suit :

const dot = require('dot-object');

function(docid, varname, varvalue){
  let doc = dot.dot({
      [varname]: varvalue 
  });

  Mongo.update({_id:docid},{$set:doc});
}

Ce modèle me permet d'utiliser indifféremment des propriétés imbriquées ou à un seul niveau, et de les insérer proprement dans Mongo.

Si vous avez besoin de jouer avec les objets JS au-delà de Mongo, en particulier du côté client, mais que vous voulez être cohérent avec Mongo, cette bibliothèque vous offre plus d'options que les précédentes. mongo-dot-notation Module NPM.

P.S. Je voulais à l'origine mentionner ceci en tant que commentaire mais apparemment mon rapport S/O n'est pas assez élevé pour poster un commentaire. Je n'essaie pas de m'immiscer dans le commentaire de SzybkiSasza, je voulais simplement souligner l'importance de fournir un module alternatif.

1voto

nick-s Points 410

J'ai essayé findAndModify() pour mettre à jour un champ particulier dans un objet préexistant.

https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X