Использование MongoCollection.FindAll возвращает один и тот же документ дважды

Мы столкнулись с ошибкой в ​​нашей системе, вызванной получением дубликатов документов из MongoDB. Это происходит при использовании FindAll при одновременном обновлении коллекции из другого процесса.

Как лучше всего этого избежать?

Мы не против получить устаревшую версию только что обновленного документа, получить только что удаленные документы или пропустить только что вставленные документы.

Мы видели, что существует SetSnapshot параметр для курсоров ($snapshot: true ), но каковы последствия для производительности? Почему он не включен по умолчанию?

Мы можем удалить возвращенные дубликаты вручную, но это кажется неправильным и также может снизить производительность.


Обновление:

Насколько мы понимаем, обновления, изменяющие размер документа, могут перемещать его местоположение в коллекции. Если такое обновление происходит во время операции FindAll, когда параметр $snapshot выключен, документ может быть возвращен дважды.


Обновление 2:

Удаление дубликатов вручную на стороне клиента (в памяти) не является вариантом, поскольку некоторые документы могут быть потеряны (по тем же причинам они могут появляться дважды).


person Kaiser Soze    schedule 21.10.2014    source источник


Ответы (1)


Там есть FAQ. для этого, что в основном говорит о том, что вы можете предотвратить появление дублирующихся документов в вашем запросе одним из следующих способов:

  • Используется $snapshot, но это нельзя использовать с сегментированными коллекциями или sort()
  • Сортировка вашего запроса по полю, которое не изменяется и имеет уникальный индекс

Поэтому используйте $snapshot, если его ограничения не создают для вас проблем, или отсортируйте результаты по статическому, однозначно проиндексированному полю, например _id, используя hint(), если необходимо, чтобы убедиться, что оно используется. Сделайте профилирование с explain(), чтобы проверить свои возможности.

$snapshot не включен по умолчанию из-за его ограничений.

person JohnnyHK    schedule 21.10.2014
comment
Спасибо, мы видели этот FAQ, но можно ли это сделать? Будет ли это вызывать больше поисков, чем поиск без запроса? И если это так, то не лучше ли удалить дубликаты в памяти после поиска? - person Kaiser Soze; 21.10.2014
comment
Да, это правильный путь. Удаление дубликатов на стороне клиента, вероятно, будет медленнее и определенно более беспорядочным. - person JohnnyHK; 21.10.2014
comment
Удаление дубликатов на стороне клиента невозможно - некоторые существующие документы могут вообще не быть возвращены. Знаете ли вы, может ли опция $snapshot иметь отрицательное влияние на производительность? Спасибо еще раз за помощь :) - person Kaiser Soze; 21.10.2014
comment
Я не совсем понимаю, что вы имели в виду в последнем комментарии. Под клиентской стороной я просто подразумеваю удаление дубликатов в памяти после поиска. - person JohnnyHK; 21.10.2014
comment
Извините за нечеткий комментарий и быстрое редактирование. Я имел в виду, что после некоторого тестирования мы обнаружили, что обновленные документы могут возвращаться дважды, ИЛИ они могут не возвращаться вообще. - person Kaiser Soze; 21.10.2014
comment
Верно. Видишь ли, я же сказал тебе, что это грязнее. :) - person JohnnyHK; 21.10.2014
comment
Давайте продолжим это обсуждение в чате. - person Kaiser Soze; 21.10.2014