Angenommen, wir haben die folgende Sammlung, zu der ich einige Fragen habe:
{
"_id" : ObjectId("4faaba123412d654fe83hg876"),
"user_id" : 123456,
"total" : 100,
"items" : [
{
"item_name" : "my_item_one",
"price" : 20
},
{
"item_name" : "my_item_two",
"price" : 50
},
{
"item_name" : "my_item_three",
"price" : 30
}
]
}
1 - Ich möchte den Preis für "item_name" erhöhen: "my_item_two". Wenn er nicht vorhanden ist , sollte er an das Array "items" angehängt werden.
2 - Wie kann ich zwei Felder gleichzeitig aktualisieren? Erhöhen Sie beispielsweise den Preis für "my_item_three" und erhöhen Sie gleichzeitig die "Summe" (mit demselben Wert).
Ich bevorzuge dies auf der MongoDB-Seite, andernfalls muss ich das Dokument auf der Clientseite (Python) laden und das aktualisierte Dokument erstellen und durch das vorhandene in MongoDB ersetzen.
UPDATE Dies ist, was ich versucht habe und funktioniert gut, wenn das Objekt existiert :
db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})
Aber wenn der Schlüssel nicht existiert, tut er nichts. Außerdem wird nur das verschachtelte Objekt aktualisiert. Mit diesem Befehl kann auch das Feld "total" nicht aktualisiert werden.
Antworten:
Lassen Sie uns Frage 1 in zwei Teile teilen. Erhöhen Sie zunächst jedes Dokument mit "items.item_name" gleich "my_item_two". Dazu müssen Sie den Positionsoperator "$" verwenden. Etwas wie:
Beachten Sie, dass dadurch nur das erste übereinstimmende Unterdokument in einem Array inkrementiert wird. Wenn Sie also ein anderes Dokument im Array mit "item_name" gleich "my_item_two" haben, wird es nicht inkrementiert). Aber das könnte sein, was Sie wollen.
Der zweite Teil ist schwieriger. Wir können ein neues Element wie folgt ohne "my_item_two" in ein Array verschieben:
Für Ihre Frage Nr. 2 ist die Antwort einfacher. Um die Summe und den Preis von item_three in einem Dokument zu erhöhen, das "my_item_three" enthält, können Sie den Operator $ inc für mehrere Felder gleichzeitig verwenden. Etwas wie:
quelle
Es gibt keine Möglichkeit, dies in einer einzelnen Abfrage zu tun. Sie müssen das Dokument in der ersten Abfrage durchsuchen:
Wenn ein Dokument vorhanden ist:
Sonst
Keine Notwendigkeit, Bedingung hinzuzufügen
{$ne : "my_item_two" }
.Auch in Multithread-Umgebungen müssen Sie darauf achten, dass jeweils nur ein Thread den zweiten ausführen kann (Groß- / Kleinschreibung einfügen, wenn das Dokument nicht gefunden wurde). Andernfalls werden doppelte eingebettete Dokumente eingefügt.
quelle
Wir können den
$set
Operator verwenden, um das verschachtelte Array innerhalb des abgelegten Objekts zu aktualisieren und den Wert zu aktualisierenquelle