Является ли перемещение документов между коллекциями хорошим способом представления изменений состояния в MongoDB?
У меня есть две коллекции: одна (A), содержащая элементы для обработки (относительно небольшие) и один ( B) с уже обработанными (довольно большими, с дополнительными поля результатов).
Элементы читаются с A, обрабатываются и сохраняются() 'd до B, а затем удаляются()' d из A.
Обоснование заключается в том, что индексы могут быть разными между ними и что "входящая" коллекция может храниться очень малой и быстрой таким образом.
Я столкнулся с двумя проблемами:
- если вы удаляете() или сохраняете() тайм-аут или иным образом терпите неудачу при загрузке, я полностью теряю элемент или обрабатываю его дважды
- если оба не работают, побочные эффекты происходят, но нет записи о том, что
Я могу обойти случай с двойным сбоем с помощью блокировок findAndModify (в противном случае не требуется блокировка на уровне процесса), но тогда у нас есть проблемы с устаревшим блокированием, и частичные сбои все еще могут произойти. Невозможно ли физически удалить + сохранить в разные коллекции, насколько я могу судить (может быть, по дизайну?)
Есть ли лучшая практика для этой ситуации?
Ответы
Ответ 1
Невозможно физически удалить + сохранить в разные коллекции, насколько я могу судить (возможно, по дизайну?)
Да, это по дизайну. MongoDB явно не предоставляет объединения или транзакции. Удалить + Сохранить - это форма транзакции.
Есть ли лучшая практика для этой ситуации?
У вас действительно есть два варианта с низкой степенью сложности, оба включают findAndModify
.
Вариант №1: отдельная коллекция
Основываясь на вашем описании, вы в основном создаете очередь с некоторыми дополнительными функциями. Если вы используете одну коллекцию, вы используете findAndModify
для обновления состояния каждого элемента по мере его обработки.
К сожалению, это означает, что вы потеряете это:... что "входящая" коллекция может храниться очень малой и быстрой.
Вариант № 2: две коллекции
Другим вариантом является в основном двухфазное принятие, используя findAndModify
.
Взгляните на документы для этого здесь.
Как только элемент обрабатывается в A, вы устанавливаете для него поле для его удаления. Затем вы копируете этот элемент на B. После копирования в B вы можете удалить элемент из A.
Ответ 2
Я еще не пробовал это сам, но новая книга 50 советов и советов для разработчиков MongoDB несколько раз упоминает о использовании заданий cron (или служб/планировщиков) для очистки данных, подобных этому. Вы можете оставить документы в коллекции A помечены для удаления и запустить ежедневную работу, чтобы очистить их, уменьшив общую область исходной транзакции.
Из того, что я узнал до сих пор, я никогда не покидал базу данных в состоянии, когда я полагаюсь на следующее действие базы данных, если оно не является последним действием (журналирование будет повторно отправить последнее действие db при восстановлении). Например, у меня есть процесс регистрации трехэтапной учетной записи, когда я создаю пользователя в CollectionA, а затем добавляю другой связанный документ в CollectionB. Когда я создаю пользователя, я вставляю детали документа CollectionB в CollectionA в случае неудачной записи второй записи. Позже я напишу процесс, который удаляет встроенные данные из CollectionA, если документ в CollectionB существует
Не имея транзакций, это вызывает такие болевые точки, но я думаю, что в некоторых случаях есть новые способы думать об этом. В моем случае время покажет, как я продвигаюсь с моим приложением