Безопасный и эффективный способ изменения объектов Mongo при переборе курсора?

У меня есть код, который проверяет каждый объект в коллекции Mongo (перебирая результат find() без параметров) и вносит изменения в некоторые из них. Кажется, это небезопасно: мои изменения сохраняются, но затем, когда я продолжаю перебирать курсор, подмножество измененных объектов (10-15%) появляется во второй раз. Я не менял идентификатор документа или что-то еще, на что есть индекс.

Я полагаю, что мог бы избежать этой проблемы, заранее захватив все идентификаторы документов (преобразовав курсор в массив), но это большие коллекции, поэтому я бы очень хотел этого избежать.

Я заметил, что результат find() по умолчанию не имеет определенного порядка, поэтому я попытался указать явную сортировку курсора {"_id":1}. Кажется, это устранило проблему - теперь ничего не появляется дважды, независимо от того, что я изменяю. Но я не знаю, хороший ли это/надежный подход. Насколько я могу судить из документации, добавление сортировки не приводит к предварительному запросу всех идентификаторов; если да, то это хорошо, но тогда я не знаю, почему это решит проблему.

Это просто плохая идея использовать курсоры при изменении материала?

Я использую Scala/Casbah, если это имеет значение.


person Eli Bishop    schedule 17.04.2012    source источник


Ответы (2)


Похоже, вам нужен запрос моментального снимка. Вот дополнительная информация о том, как это сделать:

http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database

person mpobrien    schedule 17.04.2012
comment
Именно то, что я искал - просто не знал, как это называется. Спасибо! - person Eli Bishop; 18.04.2012

Рассмотрите возможность использования команды update, которая изменяет несколько документов: http://docs.mongodb.org/manual/tutorial/modify-documents/

Кроме того, поскольку вы изменяете только некоторые объекты, рассмотрите возможность использования запроса, который возвращает только те документы, которые вы действительно собираетесь изменить, а не сканирует всю коллекцию.

Повторение результата find и изменение объектов может показаться более удобным и гибким, поскольку вы не ограничены тем, что вы можете делать с операторами обновления, и вы можете написать код на выбранном вами языке для изменения документа. Однако есть проблема, которую вы описали, а также другие ограничения:

http://docs.mongodb.org/manual/faq/developers/#faq-developers-isolate-cursors

Например, снэпшот-запросы не на 100% безопасны, и их нельзя использовать с сегментированной коллекцией, поэтому, если вы позже решите шардировать, ваше решение сломается.

Если вам нужно изменить очень большое количество объектов более сложным способом, возможно, map-reduce или конвейер агрегации могут решить вашу проблему:

http://docs.mongodb.org/manual/core/aggregation-pipeline/

http://docs.mongodb.org/manual/core/map-reduce/

person Florian Winter    schedule 01.08.2014