Есть ли способ атомарно обновить две коллекции в MongoDB? - PullRequest
17 голосов
/ 22 мая 2011

У меня есть коллекция сообщений:

{
    messageid: ObjectId
    userid: ObjectId
    message: string
    isread: true|false
}

и набор сообщений для каждого пользователя:

{
    userid: ObjectId
    total: int
    unread: int
}

Когда я удаляю сообщение из коллекции "messages", я такженеобходимо уменьшить «общее» в коллекции «count» и условно (если «messages.isread» == false) также уменьшить «непрочитанное» поле.

Для этого мне нужно сначала получить сообщение, проверьтеего «isread» поле, а затем обновите счетчики.Существует вероятность того, что сообщение будет помечено как прочитанное между этими действиями, тогда я уменьшу количество непрочитанных сообщений неправильно.

Есть ли способ условно изменить что-либо в одной коллекции на основе результатов другой коллекции в одном кадре?

Ответы [ 5 ]

13 голосов
/ 23 мая 2011

Здесь есть много ответов, но я хочу заполнить все пробелы здесь:

Есть ли способ атомарно обновить две коллекции в MongoDB?

Нет.Атомарное обновление двух коллекций фактически является транзакцией.MongoDB не поддерживает транзакции между коллекциями или даже внутри коллекции.

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

Есть ли способ условно изменить что-то в одной коллекции на основе результатов другой коллекции в одном кадре?

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

Триггеры еще не реализованы , так что это не такдействительно вариант в вашем случае.

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

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

4 голосов
/ 23 мая 2011

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

1 голос
/ 23 мая 2011

MongoDB очень быстрый, поэтому, если ваш сайт не загружен, вы можете просто пересчитать общее количество сообщений и общее количество сообщений, прочитанных по каждому запросу.Только поставить индекс на isread.Подсчет кажется очень быстрым, даже для большого объема данных.

Фактически, ваши полные и непрочитанные поля - это просто кэши.Вы действительно нуждаетесь в этом?

Здесь возникает вопрос о схожей проблеме: MongoDB: количество вызовов () и количество отслеживаний в коллекции

1 голос
/ 23 мая 2011

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

0 голосов
/ 23 мая 2011

Вы можете сделать это с помощью триггера в sql. Но в монго триггера нет.

Вы можете выполнить операцию с одним из документов и проверить LastErrorMessage для этой операции, установив SafeMode.True

Тогда, если ошибок нет, обновите второй сборник.

В настоящее время нет способа сделать это атомарным способом.

Если бы было, я бы использовал в своем проекте. Мне тоже нужна была эта функциональность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...