Was ist der Unterschied zwischen findAndModify und Update in MongoDB?

175

Ich bin ein bisschen verwirrt von der findAndModifyMethode in MongoDB. Was ist der Vorteil gegenüber der updateMethode? Für mich scheint es, dass es nur das Element zuerst zurückgibt und es dann aktualisiert. Aber warum muss ich den Artikel zuerst zurückgeben? Ich habe die MongoDB gelesen : die endgültige Anleitung und sie besagt, dass sie praktisch ist, um Warteschlangen zu manipulieren und andere Operationen auszuführen, die eine Atomizität im Get-and-Set-Stil erfordern. Aber ich habe nicht verstanden, wie das erreicht wird. Kann mir das jemand erklären?

chaonextdoor
quelle

Antworten:

153

Wenn Sie ein Element abrufen und dann aktualisieren, kann zwischen diesen beiden Schritten eine Aktualisierung durch einen anderen Thread erfolgen. Wenn Sie ein Element zuerst aktualisieren und dann abrufen, liegt möglicherweise ein weiteres Update dazwischen vor, und Sie erhalten ein anderes Element als das, das Sie aktualisiert haben, zurück.

Wenn Sie dies "atomar" tun, wird Ihnen garantiert, dass Sie genau das gleiche Element zurückerhalten, das Sie aktualisieren - dh es kann kein anderer Vorgang dazwischen ausgeführt werden.

Asya Kamsky
quelle
6
Ich bin immer noch ein bisschen verwirrt. Wie kann findAndModifysichergestellt werden, dass kein anderer Aktualisierungsvorgang den Vorgang stört?
Chaonextdoor
78
@chaonextdoor findAndModify erhält beim Starten des Vorgangs eine Sperre für die Datenbank, sodass kein anderer Vorgang verarbeitet werden kann, wenn er ausgeführt wird. Wenn der Vorgang abgeschlossen ist, wird die Sperre aufgehoben.
Lycha
4
findAndModify erhält erst dann eine Sperre, wenn der Teil der Anforderung geändert wurde. Es ist also möglich, dass mehrere Prozesse denselben Datensatz aktualisieren können.
Mark Unsworth
5
@MarkUnsworth öffnen Sie einen Support-Fall mit 10gen - wenn es einen Fehler beim Sperren mit findAndModify gibt, kann ich Ihnen garantieren, dass Ingenieure ihn so schnell wie möglich beheben möchten. Wenn dies der Fall wäre, würden viele Leute dieses Verhalten melden, aber findAndModify funktioniert so, wie es für so ziemlich jeden entwickelt wurde, der es verwendet - Fälle, in denen es den Anschein hatte, als sei es nicht auf Logik- oder Implementierungsfehler auf der Clientseite zurückzuführen Aber natürlich kann es in komplexer Software immer einen Fehler geben.
Asya Kamsky
4
@AsyaKamsky Ich habe überlegt, mit dir zu streiten, aber dann wurde mir klar, dass du Recht hast. Jetzt denke ich, ich sollte mich entschuldigen. Es tut uns leid!
funkyeah
54

findAndModify gibt das Dokument zurück, die Aktualisierung nicht.

Wenn ich Dwight Merriman (einen der ursprünglichen Autoren von mongoDB) richtig verstanden habe, ist die Verwendung von update zum Ändern eines einzelnen Dokuments, dh ("multi": false}, ebenfalls atomar. Derzeit sollte es auch schneller sein als das entsprechende Update mit findAndModify.

Yaniv
quelle
31

Aus den MongoDB-Dokumenten (Hervorhebung hinzugefügt):

  • Standardmäßig ändern beide Vorgänge ein einzelnes Dokument. Die update () -Methode mit ihrer Multi-Option kann jedoch mehr als ein Dokument ändern .

  • Wenn mehrere Dokumente den Aktualisierungskriterien entsprechen, können Sie für findAndModify () eine Sortierung angeben , um ein gewisses Maß an Kontrolle darüber zu erhalten, welches Dokument aktualisiert werden soll. Mit dem Standardverhalten der update () -Methode können Sie nicht angeben, welches einzelne Dokument aktualisiert werden soll, wenn mehrere Dokumente übereinstimmen.

  • Standardmäßig gibt die Methode findAndModify () die vorab geänderte Version des Dokuments zurück . Verwenden Sie die neue Option, um das aktualisierte Dokument zu erhalten. Die update () -Methode gibt ein WriteResult-Objekt zurück, das den Status der Operation enthält. Verwenden Sie die Methode find (), um das aktualisierte Dokument zurückzugeben. Andere Aktualisierungen haben jedoch möglicherweise das Dokument zwischen Ihrer Aktualisierung und dem Abrufen von Dokumenten geändert. Wenn durch die Aktualisierung nur ein einzelnes Dokument geändert wurde, jedoch mehrere Dokumente übereinstimmten, müssen Sie zusätzliche Logik verwenden, um das aktualisierte Dokument zu identifizieren.

  • Vor MongoDB 3.2 können Sie für findAndModify () kein Schreibproblem angeben, um das Standardschreibproblem zu überschreiben, während Sie seit MongoDB 2.6 ein Schreibproblem für die update () -Methode angeben können .

Beim Ändern eines einzelnen Dokuments aktualisieren sowohl findAndModify () als auch die update () -Methode das Dokument atomar.

Tamlyn
quelle
1
Sie können jederzeit Schreibprobleme angeben, um den Vorgang zu aktualisieren. Darüber hinaus können Sie seit 3.2 (3.1.1 technisch) auch Schreibprobleme für findAndModify angeben. jira.mongodb.org/browse/SERVER-6558
Asya Kamsky
Ich habe festgestellt, dass in MongDB 3.6, obwohl das Dokument findAndModify()standardmäßig nur ein Dokument ändert und update()ein oder mehrere Dokumente aktualisieren kann, wenn ich ein verwende arrayFilters, findAndModify()alle Übereinstimmungen aktualisiert werden. Vielleicht ist es ein Fehler?
WesternGun
Es gibt keinen Fehler - Mit arrayFilters können Sie mehrere Array-Elemente aktualisieren, diese befinden sich jedoch weiterhin in einem einzigen Dokument.
Asya Kamsky
10

Eine nützliche Klasse von Anwendungsfällen sind Zähler und ähnliche Fälle. Schauen Sie sich zum Beispiel diesen Code an (einen der MongoDB-Tests): find_and_modify4.js .

Somit wird mit findAndModifyden Zählern erhöht und in einem Schritt seinen inkrementierten Wert. Vergleichen Sie: Wenn Sie (A) diese Operation in zwei Schritten ausführen und jemand anderes (B) dieselbe Operation zwischen Ihren Schritten ausführt, erhalten A und B möglicherweise denselben letzten Zählerwert anstelle von zwei verschiedenen (nur ein Beispiel für mögliche Probleme).

Roman Kuzmin
quelle
0

Wir haben findAndModify () für Counter-Operationen (inc oder dec) verwendet und andere Einzelfelder mutieren Fälle. Bei der Migration unserer Anwendung von Couchbase nach MongoDB habe ich festgestellt, dass diese API den Code für GetAndlock () ersetzt, den Inhalt lokal ändert, replace () zum Speichern und Get () erneut zum Abrufen des aktualisierten Dokuments. Bei mongoDB habe ich nur diese einzelne API verwendet, die das aktualisierte Dokument zurückgibt.

Manju Kori
quelle