Jaka jest różnica między findAndModify i update w MongoDB?

175

Jestem trochę zdezorientowany findAndModifymetodą w MongoDB. Jaka jest jego przewaga nad updatemetodą? Wydaje mi się, że najpierw zwraca element, a następnie go aktualizuje. Ale dlaczego muszę najpierw zwrócić przedmiot? Czytałem MongoDB: ostateczny przewodnik i mówi, że jest przydatny do manipulowania kolejkami i wykonywania innych operacji, które wymagają atomowości w stylu get-and-set. Ale nie rozumiałem, jak to osiąga. Czy ktoś może mi to wyjaśnić?

chaonextdoor
źródło

Odpowiedzi:

153

Jeśli pobierzesz element, a następnie go zaktualizujesz, może wystąpić aktualizacja przez inny wątek między tymi dwoma krokami. Jeśli najpierw zaktualizujesz element, a następnie go pobierzesz, w międzyczasie może nastąpić kolejna aktualizacja i otrzymasz inny element niż zaktualizowany.

Zrobienie tego „atomowo” oznacza, że ​​masz gwarancję, że odzyskasz dokładnie ten sam element, który aktualizujesz - tj. Żadna inna operacja nie może się wydarzyć pomiędzy.

Asya Kamsky
źródło
6
Nadal jestem trochę zdezorientowany. W jaki sposób findAndModifygwarantuje, że żadna inna operacja aktualizacji nie będzie mu przeszkadzać?
chaonextdoor
78
@chaonextdoor findAndModify uzyskuje blokadę bazy danych podczas uruchamiania operacji, aby żadna inna operacja nie mogła zostać przetworzona, gdy jest uruchomiona. Po zakończeniu operacji zwalnia blokadę.
Lycha
4
findAndModify nie uzyskuje blokady aż do zmodyfikowania części żądania. Dlatego możliwe jest, że wiele procesów może zaktualizować ten sam rekord.
Mark Unsworth
5
@MarkUnsworth otwórz zgłoszenie pomocy za pomocą 10gen - jeśli wystąpi błąd w blokowaniu za pomocą findAndModify, mogę zagwarantować, że inżynierowie zechcą to naprawić jak najszybciej. Gdyby tak było, to widzielibyśmy, jak wiele osób zgłasza to zachowanie, ale findAndModify działa zgodnie z przeznaczeniem dla prawie każdego, kto go używa - przypadków, w których wydawało się, że nie wynikało to z błędów logiki lub implementacji po stronie klienta , ale oczywiście w złożonym oprogramowaniu zawsze może wystąpić błąd.
Asya Kamsky
4
@AsyaKamsky Rozważałem kłótnię z tobą, ale potem zdałem sobie sprawę, że masz rację, więc teraz myślę, że powinienem przeprosić. Przepraszam!
funkyeah
54

findAndModify zwraca dokument, aktualizacja nie.

Jeśli dobrze zrozumiałem Dwighta Merrimana (jednego z oryginalnych autorów mongoDB), użycie update do modyfikacji pojedynczego dokumentu, tj. ("Multi": false} również jest atomowe. Obecnie powinno być również szybsze niż wykonanie równoważnej aktualizacji przy użyciu findAndModify.

Yaniv
źródło
31

Z dokumentacji MongoDB (podkreślenie dodane):

  • Domyślnie obie operacje modyfikują pojedynczy dokument. Jednak metoda update () z opcją multi może modyfikować więcej niż jeden dokument .

  • Jeśli wiele dokumentów spełnia kryteria aktualizacji, dla funkcji findAndModify () można określić sortowanie, aby zapewnić pewną kontrolę nad tym, który dokument ma zostać zaktualizowany. Przy domyślnym działaniu metody update () nie można określić, który pojedynczy dokument ma zostać zaktualizowany, gdy pasuje wiele dokumentów.

  • Domyślnie metoda findAndModify () zwraca wstępnie zmodyfikowaną wersję dokumentu . Aby uzyskać zaktualizowany dokument, użyj nowej opcji. Metoda update () zwraca obiekt WriteResult, który zawiera stan operacji. Aby zwrócić zaktualizowany dokument, użyj metody find (). Jednak inne aktualizacje mogły zmodyfikować dokument między aktualizacją a pobraniem dokumentu. Ponadto, jeśli aktualizacja zmodyfikowała tylko jeden dokument, ale dopasowano wiele dokumentów, będziesz musiał użyć dodatkowej logiki, aby zidentyfikować zaktualizowany dokument.

  • Przed MongoDB 3.2 nie można określić problemu zapisu dla findAndModify (), aby zastąpić domyślny problem zapisu, natomiast można określić problem zapisu w metodzie update () od wersji MongoDB 2.6.

Podczas modyfikowania pojedynczego dokumentu zarówno metoda findAndModify (), jak i metoda update () niepodzielnie aktualizują dokument.

Tamlyn
źródło
1
Zawsze możesz określić problem zapisu w operacji aktualizacji. Ponadto, od wersji 3.2 (technicznie 3.1.1) możesz określić problem zapisu również dla findAndModify. jira.mongodb.org/browse/SERVER-6558
Asya Kamsky
Zauważyłem, że w MongDB 3.6, chociaż dokument stwierdza findAndModify(), że domyślnie modyfikuje tylko jeden dokument i update()może aktualizować jeden lub więcej dokumentów, kiedy używam arrayFilters, findAndModify()aktualizuje wszystkie dopasowania. Może to błąd ??
WesternGun
Nie ma błędu - arrayFilters pozwala aktualizować wiele elementów tablicy, ale nadal znajdują się one w jednym dokumencie.
Asya Kamsky
10

Jedną z przydatnych klas przypadków użycia są liczniki i podobne przypadki. Na przykład spójrz na ten kod (jeden z testów MongoDB): find_and_modify4.js .

Zatem wraz z findAndModifytobą zwiększaj licznik i uzyskuj jego zwiększoną wartość w jednym kroku. Porównaj: jeśli (A) wykonasz tę operację w dwóch krokach, a ktoś inny (B) wykona tę samą operację między twoimi krokami, A i B mogą otrzymać tę samą ostatnią wartość licznika zamiast dwóch różnych (tylko jeden przykład możliwych problemów).

Roman Kuzmin
źródło
0

Użyliśmy metody findAndModify () dla operacji licznika (inc lub dec) i innych pojedynczych pól mutacji przypadków. Migracja naszej aplikacji z Couchbase do MongoDB, znalazłem to API, aby zastąpić kod, który wykonuje GetAndlock (), zmodyfikować zawartość lokalnie, replace (), aby zapisać i ponownie Get (), aby pobrać zaktualizowany dokument z powrotem. W mongoDB właśnie użyłem tego pojedynczego interfejsu API, który zwraca zaktualizowany dokument.

Manju Kori
źródło