Есть ли способ атомного обновления двух коллекций в MongoDB?

У меня есть набор сообщений:

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

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

{
    userid: ObjectId
    total: int
    unread: int
}

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

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

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

Ответы

Ответ 1

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

Есть ли способ атомного обновления двух коллекций в MongoDB?

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

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

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

В документе atomic updates есть некоторые документы. Однако вам действительно нужна очередь и некоторая форма двухфазная фиксация или вам нужны триггеры.

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

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

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

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

Затем, если нет ошибки, обновите вторую коллекцию.

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

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