Comment puis-je partiellement mise à jour d'un objet dans MongoDB, de sorte que le nouvel objet de superposition ou de fusionner avec l'existant
Compte tenu de ce document enregistré dans MongoDB
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2",
param3 : "val3"
}
}
Un objet avec de nouvelles informations sur param2
et param3
du monde extérieur doit être enregistré
var new_info = {
param2 : "val2_new",
param3 : "val3_new"
};
Je veux fusionner /la superposition de nouveaux champs sur l'état actuel de l'objet, de sorte que param1 n'a pas supprimé
Faire ce
db.collection.update( { _id:...} , { $set: { some_key : new_info } }
Conduira à MongoDB est en train de faire exactement comme il a été demandé, et définit some_key à cette valeur. pour remplacer l'ancien.
{
_id : ...,
some_key: {
param2 : "val2_new",
param3 : "val3_new"
}
}
Quel est le moyen d'avoir MongoDB mise à jour uniquement les nouveaux champs (sans les énoncer un par un de manière explicite)? pour obtenir ceci:
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2_new",
param3 : "val3_new"
}
}
Je suis en utilisant le client Java, mais aucun exemple sera apprécié
- merci de voter pour le $fusionner question: jira.mongodb.org/browse/SERVER-21094
Vous devez vous connecter pour publier un commentaire.
Si je comprends correctement à 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 les champs qui sont déjà (même si à une autre valeur).
Il n'y a aucun moyen de le faire en une seule commande.
Vous devez interroger le document tout d'abord, déterminez ce que vous voulez
$set
et puis la mise à jour (en utilisant les anciennes valeurs en tant que correspondant du filtre pour vous assurer de ne pas obtenir les mises à jour simultanées entre les deux).Une autre lecture de votre question peut être que vous êtes heureux avec
$set
, mais ne souhaitez pas définir explicitement tous les domaines. Comment voulez-vous passer dans les données, alors?Vous savez que vous pouvez effectuer les opérations suivantes:
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 dont vous avez besoin pour répondre clairement.
Exemple:
Si vous souhaitez mettre à jour param2 seulement, il est faux de faire:
Vous devez utiliser:
J'ai donc écrit une fonction quelque chose comme ça:
db.users.update( { _id: ObjectId("594dbc3186bb5c84442949b1") }, { $set: { resume: { url: "http://i.imgur.com/UFX0yXs.jpg" } } } )
Vous pouvez utilisez le point-notation d'accès et de définir les champs de profondeur à l'intérieur 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 vous plonger aussi profondément que vous le souhaitez. C'est aussi utile pour l'ajout de nouvelles propriétés à un objet sans en modifier ceux existants.
La meilleure solution est d'extraire les propriétés de l'objet et de les rendre plat dot notation des paires clé-valeur. Vous pouvez utiliser par exemple cette bibliothèque:
https://www.npmjs.com/package/mongo-dot-notation
Il a
.flatten
fonction qui permet de modifier l'objet dans le plat ensemble de propriétés qui pourraient alors être donnée à $définir modificateur, sans soucis que toute propriété de votre base de données existante de l'objet sera supprimé/remplacé sans nécessité.Prises de
mongo-dot-notation
docs:Et puis elle a des formes parfaite sélecteur - il SEULEMENT à jour les propriétés données.
EDIT: je tiens à être archéologue, à certains moments 😉
Mongo permet de mettre à jour documents imbriqués à l'aide d'un
.
convention. Prendre un coup d'oeil: La mise à jour de documents imbriqués dans mongodb. Voici une autre question du passé à propos d'une fusion de mise à jour, comme celui que vous recherchez je crois: MongoDB atomique de mise à jour via "fusionner" documentJ'ai eu du succès en le faisant de cette manière:
J'ai une fonction qui s'occupe de mon profil mises à jour dynamiquement
Remarque: "profil" est spécifique à ma place, il est juste la chaîne de la clé que vous souhaitez modifier.
Il semble que vous pouvez définir isPartialObject qui pourrait accomplir ce que vous voulez.
Si vous avez plusieurs champs à mettre à jour
Ouais, la meilleure façon est de convertir l'objet de la notation d'une clé plate chaîne de valeur de la représentation, comme mentionné dans ce commentaire: https://stackoverflow.com/a/39357531/2529199
Je voulais mettre en évidence une méthode alternative à l'aide de cette MNP bibliothèque: https://www.npmjs.com/package/dot-object qui vous permet de manipuler différents objets à l'aide de la notation point.
J'ai utilisé ce modèle pour en programmant créer un objet imbriqué de la propriété lors de l'acceptation de la clé-valeur en fonction de la variable, comme suit:
Ce modèle me permet d'utiliser imbriqués, ainsi que des propriétés de niveau de façon interchangeable, et de les insérer proprement dans Mongo.
Si vous avez besoin de jouer avec des Objets JS-delà de Mongo, en particulier sur le côté client, mais avoir de la consistance lorsque l'on travaille avec Mongo, cette bibliothèque vous donne plus d'options que la précédente mentionné
mongo-dot-notation
MNP module.P. S a l'origine je voulais juste mentionner que l'un commentaire mais apparemment, mon S/O rep n'est pas suffisamment élevée pour poster un commentaire. Donc, ne pas essayer de muscle sur SzybkiSasza commentaire, je voulais juste mettre en évidence fournir un autre module.
utiliser $ensemble de faire de ce processus
Faire une mise à jour de l'objet avec les noms de propriété, y compris le nécessaire point de chemin. ("somekey."+ de l'OP de l'exemple), puis utilisez-faire la mise à jour.
J'ai essayé
findAndModify()
pour mettre à jour un champ dans un objet préexistant.https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
De départ
Mongo 4.2
,db.collection.mise à jour()
peut accepter une agrégation de pipeline, ce qui permet d'utiliser les opérateurs d'agrégation tels que$addFields
, qui affiche tous les champs de la saisie de documents et de nouveaux champs ajoutés:La première partie
{}
est le match de la requête, le filtrage des documents à mettre à jour (dans ce cas, tous les documents).La deuxième partie
[{ $addFields: { some_key: new_info } }]
est la mise à jour de l'agrégation pipeline:$addFields
.$addFields
effectue exactement ce dont vous avez besoin: la mise à jour de l'objet, de sorte que le nouvel objet sera de superposition ou de fusionner avec l'existant:{ param2: "val2_new", param3: "val3_new" }
seront fusionnés dans l'existantsome_key
en gardantparam1
intact, et ajouter ou de remplacer les deuxparam2
etparam3
.N'oubliez pas
{ multi: true }
, sinon seul le premier document correspondant sera mis à jour.Dans Mongo 3.6 il y a une fonction mergeObjects en train de faire exactement ce dont vous avez besoin:
https://docs.mongodb.com/manual/reference/operator/aggregation/mergeObjects/