В чем разница между findAndModify и update в MongoDB?

123

Я немного смущен методом findAndModify в MongoDB. Каково преимущество этого метода update? Для меня кажется, что он просто возвращает элемент первым, а затем обновляет его. Но почему мне нужно сначала вернуть элемент? Я прочитал MongoDB: окончательное руководство, и он говорит, что он удобен для манипулирования очередями и выполнения других операций, требующих атомарности стиля get-and-set. Но я не понимал, как это достигается. Может ли кто-нибудь объяснить это мне?

Теги:

4 ответа

119
Лучший ответ

Если вы извлечете элемент и затем обновите его, может быть обновление другим потоком между этими двумя шагами. Если вы сначала обновите элемент, а затем извлечете его, может быть другое промежуточное обновление, и вы получите другой элемент, чем тот, который вы обновили.

Выполнение этого "атомарного" означает, что вам гарантировано, что вы возвращаете тот же самый объект, который вы обновляете, т.е. никакая другая операция не может произойти между ними.

  • 4
    Я все еще немного смущен. Как findAndModify гарантирует, что никакая другая операция обновления не мешает ему?
  • 71
    @chaonextdoor findAndModify получает блокировку базы данных при запуске операции, поэтому никакая другая операция не может быть обработана при ее выполнении. Когда он заканчивает операцию, он снимает блокировку.
Показать ещё 15 комментариев
37

findAndModify возвращает документ, обновление не выполняется.

Если я правильно понял Dwight Merriman (один из оригинальных авторов mongoDB), используя обновление, чтобы изменить один документ, т.е. ( "multi": false} также является атомарным. В настоящее время он также должен быть быстрее, чем выполнение эквивалентного обновления используя findAndModify.

16

Из Документы MongoDB (выделено мной):

  • По умолчанию обе операции изменяют один документ. Однако метод update() с его опцией может изменять более одного документа.

  • Если несколько документов соответствуют критериям обновления, для findAndModify() вы можете указать сортировку, чтобы обеспечить определенную степень контроля над тем, какой документ обновлять. При поведении метода update() по умолчанию вы не можете указать, какой один документ нужно обновить, если несколько документов совпадают.

  • По умолчанию метод findAndModify() возвращает предварительно измененную версию документа . Чтобы получить обновленный документ, используйте новый вариант. Метод update() возвращает объект WriteResult, который содержит статус операции. Чтобы вернуть обновленный документ, используйте метод find(). Однако другие обновления могут изменить документ между вашим обновлением и извлечением документа. Кроме того, если обновление изменило только один документ, но несколько документов соответствовали, вам нужно будет использовать дополнительную логику для идентификации обновленного документа.

  • Вы не можете указать проблему с записью findAndModify(), чтобы переопределить проблему записи по умолчанию, тогда как, начиная с MongoDB 2.6, вы можете указать проблему записи на метод update().

При изменении одного документа оба метода findAndModify() и update() автоматически обновляют документ.

  • 0
    Вы всегда можете указать отношение записи к операции обновления. Кроме того, начиная с версии 3.2 (технически 3.1.1), вы также можете указать, что пишите для findAndModify. jira.mongodb.org/browse/SERVER-6558
  • 0
    Я обнаружил, что в MongDB 3.6, хотя состояния документов findAndModify() по умолчанию изменяет только один документ, а update() может обновлять один или несколько документов, когда я использую arrayFilters , findAndModify() обновляет все совпадения. Может быть, это ошибка?
Показать ещё 1 комментарий
7

Один полезный класс вариантов использования - это счетчики и подобные случаи. Например, взгляните на этот код (один из тестов MongoDB): find_and_modify4.js.

Таким образом, при findAndModify вы увеличиваете счетчик и получаете его прирост значение за один шаг. Сравните: если вы (A) выполните эту операцию в два этапа и выполните кто-то другой (B) выполняет ту же операцию между вашими шагами, тогда A и B могут получить одно и то же последнее значение счетчика вместо двух разных (только один пример возможных проблем).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню