2013-04-26 2 views
2

У меня есть коллекция с 100 миллионами документов. Я хочу безопасно обновлять ряд документов (безопасно я имею в виду обновление документа только в том случае, если он еще не был обновлен). Есть ли эффективный способ сделать это в Монго?Mongodb update ограниченное количество документов

Я планировал использовать оператор $ изолированных с предложением limit, но, похоже, mongo не поддерживает ограничение на обновления.

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

+1

Хмм, я не могу консулировать вас больше, чем давать ссылку JIRA. Я боюсь: https://jira.mongodb.org/browse/SERVER-1599 – Sammaye

+0

Спасибо. Я подписался, чтобы проголосовать за эту проблему :-) Теперь, чтобы найти некоторое запутанное обходное решение до тех пор, пока функция не будет реализована ... – jckdnk111

+0

«безопасно» - я не понимаю, почему ограничение связано с этим - если вы планируете обновить все документов, и вы используете «{multi: true}», тогда каждый документ будет обновляться только один раз. Не могли бы вы объяснить ваш конкретный случай использования? Я подозреваю, что может быть обход. –

ответ

1

Per Sammaye, это не похоже на «правильный» способ сделать это. Моим обходным путем было создать sequence as outlined on the mongo site и просто добавить поле «seq» для каждой записи в моей коллекции. Теперь у меня есть уникальное поле, которое надежно сортируется для обновления.

Надежная сортировка важна здесь. Я собирался просто сортировать автоматически генерируемый _id, но я быстро понял, что естественный порядок НЕ совпадает с возрастающим порядком для ObjectId (от this page похоже, что строковое значение имеет приоритет над значением объекта, которое соответствует поведению, которое я наблюдал в тестирование). Кроме того, вполне возможно, что запись будет перенесена на диск, что делает естественный порядок ненадежным для сортировки.

Теперь я могу запросить запись с наименьшим «seq», который НЕ был обновлен, чтобы получить открытую отправную точку. Затем я запрашиваю для записей с «seq» больше, чем моя начальная точка, и пропускаю (важно пропустить, поскольку «seq» может быть разреженным, если вы удаляете документы и т. Д.) Количество записей, которые я хочу обновить. Поместите предел 1 в этот запрос, и у вас есть конечная точка, не включающая. Теперь я могу выпустить обновление с запросом «updated» = 0, «seq»> = моя начальная точка и < моя конечная точка. Предполагая, что ни один другой поток не избил меня до удара, обновление должно дать мне то, что я хочу.

Вот шаги снова:

  1. создать последовательность автоматического приращения с помощью findAndModify
  2. добавить поле в вашей коллекции, которая использует последовательность автоинкрементируемого
  3. запрос, чтобы найти подходящую отправную точку : db.xx.find ({обновлено: 0}). sort ({seq: 1}). limit (1)
  4. запрос для поиска подходящей конечной точки: db.xx.find ({seq: {$ gt: startSeq}}). sort ({seq: 1}). skip (updateCount) .limit (1)
  5. обновляет коллекцию, используя начальную и конечную точки: db.xx.update ({updated: 0, seq: {$ gte: startSeq}, seq: {$ lt: endSeq}, $ isolated: 1}, {updated: 1 }, {multi: true})

Довольно болезненный, но он выполняет свою работу.