Angesichts dieses in MongoDB gespeicherten Dokuments
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2",
param3 : "val3"
}
}
Ein Objekt mit neuen Informationen zur param2
und param3
von der Außenwelt muss gespeichert werden
var new_info = {
param2 : "val2_new",
param3 : "val3_new"
};
Ich möchte die neuen Felder über den vorhandenen Status des Objekts zusammenführen / überlagern, damit param1 nicht entfernt wird
Dies tun
db.collection.update( { _id:...} , { $set: { some_key : new_info } }
Wird dazu führen, dass MongoDB genau das tut, was es verlangt hat, und some_key auf diesen Wert setzt. Ersetzen des alten.
{
_id : ...,
some_key: {
param2 : "val2_new",
param3 : "val3_new"
}
}
Wie kann MongoDB nur neue Felder aktualisieren (ohne sie explizit einzeln anzugeben)? um dies zu bekommen:
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2_new",
param3 : "val3_new"
}
}
Ich verwende den Java-Client, aber jedes Beispiel wird geschätzt
mongodb
mongodb-java
Eran Medan
quelle
quelle
Antworten:
Wenn ich die Frage richtig verstehe, möchten Sie ein Dokument mit dem Inhalt eines anderen Dokuments aktualisieren, jedoch nur mit den Feldern, die noch nicht vorhanden sind, und die bereits festgelegten Felder vollständig ignorieren (auch wenn sie einen anderen Wert haben).
Es gibt keine Möglichkeit, dies in einem einzigen Befehl zu tun.
Sie müssen das Dokument zuerst abfragen, herausfinden, was Sie möchten,
$set
und es dann aktualisieren (indem Sie die alten Werte als passenden Filter verwenden, um sicherzustellen, dass Sie nicht gleichzeitig Aktualisierungen erhalten).Eine andere Lesart Ihrer Frage wäre, dass Sie zufrieden sind
$set
, aber nicht alle Felder explizit festlegen möchten. Wie würden Sie dann die Daten weitergeben?Sie wissen, dass Sie Folgendes tun können:
quelle
db.collection.update( { _id:...} , { $set: someObjectWithNewData, { $multi: true } } )
Ich habe es mit meiner eigenen Funktion gelöst. Wenn Sie das angegebene Feld im Dokument aktualisieren möchten, müssen Sie es klar ansprechen.
Beispiel:
Wenn Sie nur param2 aktualisieren möchten, ist dies falsch:
Sie müssen verwenden:
Also habe ich so eine Funktion geschrieben:
quelle
db.users.update( { _id: ObjectId("594dbc3186bb5c84442949b1") }, { $set: { resume: { url: "http://i.imgur.com/UFX0yXs.jpg" } } } )
Sie können die Punktnotation verwenden, um auf Felder tief in Objekten zuzugreifen und diese festzulegen, ohne die anderen Eigenschaften dieser Objekte zu beeinflussen.
Angesichts des oben angegebenen Objekts:
Wir können nur aktualisieren
some_key.param2
undsome_key.param3
:Sie können so tief eintauchen, wie Sie möchten. Dies ist auch nützlich, um einem Objekt neue Eigenschaften hinzuzufügen, ohne die vorhandenen zu beeinflussen.
quelle
Die beste Lösung besteht darin, Eigenschaften aus dem Objekt zu extrahieren und sie zu flachen Schlüssel-Wert-Paaren mit Punktnotation zu machen. Sie könnten zum Beispiel diese Bibliothek verwenden:
https://www.npmjs.com/package/mongo-dot-notation
Es hat
.flatten
Funktion, mit der Sie ein Objekt in einen flachen Satz von Eigenschaften ändern können, die dann dem Modifikator $ set zugewiesen werden können, ohne befürchten zu müssen, dass eine Eigenschaft Ihres vorhandenen DB-Objekts ohne Notwendigkeit gelöscht / überschrieben wird.Entnommen aus
mongo-dot-notation
Dokumenten:Und dann bildet es den perfekten Selektor - es aktualisiert NUR die angegebenen Eigenschaften. EDIT: Ich bin manchmal gerne Archäologe;)
quelle
Mit Mongo können Sie verschachtelte Dokumente mithilfe einer
.
Konvention aktualisieren . Schauen Sie sich das an: Aktualisieren verschachtelter Dokumente in Mongodb . Hier ist eine weitere Frage aus der Vergangenheit zu einem Zusammenführungsupdate, wie Sie es meiner Meinung nach suchen: MongoDB-Atomupdate über das Zusammenführungsdokumentquelle
Ich hatte Erfolg damit:
Ich habe eine Funktion , die meine Griffe Profil dynamisch Updates
Hinweis: 'Profil' ist spezifisch für meine Implementierung. Es ist nur die Zeichenfolge des Schlüssels, den Sie ändern möchten.
quelle
Es sieht so aus, als könnten Sie isPartialObject festlegen, um das zu erreichen, was Sie wollen.
quelle
Wenn Sie mehrere Felder aktualisieren möchten
quelle
Starten
Mongo 4.2
,db.collection.update()
kann eine Aggregation Pipeline akzeptieren, der Betreiber Aggregation ermöglicht wie$addFields
, das gibt alle vorhandenen Felder aus den Eingangsdokumenten und neu hinzugefügte Feldern:Der erste Teil
{}
ist die Übereinstimmungsabfrage, bei der gefiltert wird, welche Dokumente aktualisiert werden sollen (in diesem Fall alle Dokumente).Der zweite Teil
[{ $addFields: { some_key: new_info } }]
ist die Update-Aggregations-Pipeline:$addFields
.$addFields
führt genau das aus, was Sie benötigen: Aktualisieren des Objekts, sodass das neue Objekt mit dem vorhandenen Objekt überlagert / zusammengeführt wird:{ param2: "val2_new", param3: "val3_new" }
wird in das vorhandene zusammengeführt,some_key
indem Sieparam1
unberührt bleiben und entweder beideparam2
und entweder hinzufügen oder ersetzenparam3
.Vergessen Sie nicht
{ multi: true }
, sonst wird nur das erste übereinstimmende Dokument aktualisiert.quelle
zu
Ich hoffe das hilft!
quelle
Sie könnten lieber einen Upsert durchführen. Dieser Vorgang in MongoDB wird verwendet, um Dokumente in der Sammlung zu speichern. Wenn das Dokument den Abfragekriterien entspricht, wird ein Aktualisierungsvorgang ausgeführt, andernfalls wird ein neues Dokument in die Sammlung eingefügt.
etwas ähnliches wie unten
quelle
Verwenden Sie $ set, um diesen Vorgang auszuführen
quelle
Erstellen Sie ein Aktualisierungsobjekt mit den Eigenschaftsnamen einschließlich des erforderlichen Punktpfads. ("somekey." + aus dem Beispiel von OP), und verwenden Sie dann das Update.
quelle
Ja, der beste Weg ist, die Objektnotation in eine flache Darstellung von Schlüsselwertzeichenfolgen zu konvertieren, wie in diesem Kommentar erwähnt: https://stackoverflow.com/a/39357531/2529199
Ich wollte eine alternative Methode mit dieser NPM-Bibliothek hervorheben: https://www.npmjs.com/package/dot-object, mit der Sie verschiedene Objekte mithilfe der Punktnotation bearbeiten können.
Ich habe dieses Muster verwendet, um programmgesteuert eine verschachtelte Objekteigenschaft zu erstellen, wenn der Schlüsselwert wie folgt als Funktionsvariable akzeptiert wurde:
Mit diesem Muster kann ich verschachtelte und einstufige Eigenschaften austauschbar verwenden und sie sauber in Mongo einfügen.
Wenn Sie mit JS-Objekten außerhalb von Mongo herumspielen müssen, insbesondere auf der Clientseite, aber bei der Arbeit mit Mongo konsistent sind, bietet Ihnen diese Bibliothek mehr Optionen als das zuvor erwähnte
mongo-dot-notation
NPM-Modul.PS Ich wollte dies ursprünglich nur als Kommentar erwähnen, aber anscheinend ist mein S / O-Mitarbeiter nicht hoch genug, um einen Kommentar zu schreiben. Um nicht auf SzybkiSaszas Kommentar einzugehen, wollte ich nur die Bereitstellung eines alternativen Moduls hervorheben.
quelle
Ich habe versucht
findAndModify()
, ein bestimmtes Feld in einem bereits vorhandenen Objekt zu aktualisieren.https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
quelle
Sie sollten darüber nachdenken, das Objekt austauschbar zu aktualisieren, und dann einfach das Objekt mit den aktualisierten Feldern speichern. So etwas wie unten gemacht
quelle
Sie müssen eingebettete Dokumente verwenden (Zeichenfolge für das Pfadobjekt).
In JavaScript können Sie den Spread Operator (...) zum Aktualisieren verwenden
quelle