Compte tenu de ce document enregistré dans MongoDB
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2",
param3 : "val3"
}
}
Un objet contenant de nouvelles informations sur param2
et en param3
provenance du monde extérieur doit être enregistré
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 param1 ne soit pas supprimé
Ce faisant
db.collection.update( { _id:...} , { $set: { some_key : new_info } }
Mènera à MongoDB fait exactement comme il a été demandé, et définit some_key sur cette valeur. remplacer l'ancien.
{
_id : ...,
some_key: {
param2 : "val2_new",
param3 : "val3_new"
}
}
Comment faire pour que MongoDB ne mette à jour que les nouveaux champs (sans les déclarer explicitement un par un)? 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é
mongodb
mongodb-java
Eran Medan
la source
la source
Réponses:
Si je comprends bien la question, vous souhaitez mettre à jour un document avec le contenu d'un autre document, mais uniquement les champs qui ne sont pas déjà présents, et ignorer complètement les champs qui sont déjà définis (même s'ils ont une autre valeur).
Il n'y a aucun moyen de faire cela en une seule commande.
Vous devez d'abord interroger le document, déterminer ce que vous voulez
$set
, puis le mettre à jour (en utilisant les anciennes valeurs comme filtre correspondant pour vous assurer de ne pas obtenir de mises à jour simultanées entre les deux).Une autre lecture de votre question serait que vous êtes satisfait
$set
, mais que vous ne voulez pas définir explicitement tous les champs. Comment transmettriez-vous les données alors?Vous savez que vous pouvez faire ce qui suit:
la source
db.collection.update( { _id:...} , { $set: someObjectWithNewData, { $multi: true } } )
Je l'ai résolu avec ma propre fonction. Si vous souhaitez mettre à jour le champ spécifié dans le document, vous devez le traiter clairement.
Exemple:
Si vous ne souhaitez mettre à jour que param2, vous ne devez pas le faire:
Tu dois utiliser:
Alors j'ai écrit une fonction quelque chose comme ça:
la source
db.users.update( { _id: ObjectId("594dbc3186bb5c84442949b1") }, { $set: { resume: { url: "http://i.imgur.com/UFX0yXs.jpg" } } } )
Vous pouvez utiliser la notation par points pour accéder et définir des champs au cœur des objets, sans affecter les autres propriétés de ces objets.
Compte tenu de l'objet que vous avez spécifié ci-dessus:
Nous pouvons mettre à jour juste
some_key.param2
etsome_key.param3
:Vous pouvez plonger aussi profondément que vous le souhaitez. Ceci est également utile pour ajouter de nouvelles propriétés à un objet sans affecter celles existantes.
la source
La meilleure solution consiste à extraire les propriétés de l'objet et à en faire des paires clé-valeur à notation par points plates. Vous pouvez utiliser par exemple cette bibliothèque:
https://www.npmjs.com/package/mongo-dot-notation
Il a une
.flatten
fonction qui vous permet de changer l'objet en un ensemble plat de propriétés qui pourraient ensuite être attribuées à $ set modifier, sans craindre que toute propriété de votre objet DB existant soit supprimée / écrasée sans besoin.Tiré de la
mongo-dot-notation
documentation:Et puis il forme un sélecteur parfait - il ne mettra à jour QUE les propriétés données. EDIT: j'aime être archéologue parfois;)
la source
Mongo vous permet de mettre à jour les documents imbriqués à l'aide d'une
.
convention. Jetez un œil: Mise à jour des documents imbriqués dans mongodb . Voici une autre question du passé à propos d'une mise à jour de fusion, comme celle que vous recherchez je crois: mise à jour atomique MongoDB via un document `` merge ''la source
J'ai eu du succès en le faisant de cette façon:
J'ai une fonction qui gère dynamiquement les mises à jour de mon profil
Remarque: 'profile' est spécifique à mon implémentation, c'est juste la chaîne de la clé que vous souhaitez modifier.
la source
Il semble que vous puissiez définir isPartialObject qui peut accomplir ce que vous voulez.
la source
Si vous avez plusieurs champs à mettre à jour
la source
À partir de
Mongo 4.2
,db.collection.update()
peut accepter un pipeline d'agrégation, qui permet d'utiliser des opérateurs d'agrégation tels que$addFields
, qui sort tous les champs existants à partir des documents d'entrée et des champs nouvellement ajoutés:La première partie
{}
est la requête de correspondance, filtrant les documents à mettre à jour (dans ce cas, tous les documents).La deuxième partie
[{ $addFields: { some_key: new_info } }]
est le pipeline d'agrégation de mise à jour:$addFields
.$addFields
effectue exactement ce dont vous avez besoin: mettre à jour l'objet pour que le nouvel objet se superpose / fusionne avec l'existant:{ param2: "val2_new", param3: "val3_new" }
sera fusionné avec l'existantsome_key
en le gardantparam1
intact et en ajoutant ou en remplaçant les deuxparam2
etparam3
.N'oubliez pas
{ multi: true }
, sinon seul le premier document correspondant sera mis à jour.la source
à
J'espère que cette aide!
la source
Vous pouvez plutôt faire un upsert, cette opération dans MongoDB est utilisée pour enregistrer le document dans la collection. Si le document correspond aux critères de requête, il effectuera une opération de mise à jour, sinon il insérera un nouveau document dans la collection.
quelque chose de similaire comme ci-dessous
la source
utilisez $ set pour faire ce processus
la source
Créez un objet de mise à jour avec les noms de propriété, y compris le chemin de point nécessaire. ("somekey." + de l'exemple d'OP), puis utilisez-le pour effectuer la mise à jour.
la source
Oui, le meilleur moyen est de convertir la notation d'objet en une représentation de chaîne clé-valeur plate, comme mentionné dans ce commentaire: https://stackoverflow.com/a/39357531/2529199
Je voulais mettre en évidence 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 par programme une propriété d'objet imbriquée lors de l'acceptation de la valeur-clé en tant que variable de fonction, comme suit:
Ce modèle me permet d'utiliser indifféremment les propriétés imbriquées et à un seul niveau et de les insérer proprement dans Mongo.
Si vous avez besoin de jouer avec des objets JS au-delà de Mongo, en particulier du côté client, mais que vous êtes cohérent lorsque vous travaillez avec Mongo, cette bibliothèque vous offre plus d'options que le
mongo-dot-notation
module NPM mentionné précédemment .PS Je voulais à l'origine mentionner cela comme un commentaire, mais apparemment, mon représentant S / O n'est pas assez élevé pour publier un commentaire. Donc, n'essayez pas de vous muscler sur le commentaire de SzybkiSasza, je voulais juste souligner la fourniture d'un module alternatif.
la source
J'ai essayé
findAndModify()
de mettre à jour un champ particulier dans un objet préexistant.https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
la source
Vous devriez penser à mettre à jour l'objet de manière interchangeable, puis simplement stocker l'objet avec les champs mis à jour. Quelque chose comme fait ci-dessous
la source
Vous devez utiliser des documents incorporés (stringfy l'objet path)
Et donc, en JavaScript, vous pouvez utiliser Spread Operator (...) pour mettre à jour
la source