有没有办法以原子方式更新MongoDB中的两个集合?

时间:2011-05-22 19:26:41

标签: concurrency mongodb

我收到了一些邮件:

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

以及每个用户的消息计数集合:

{
    userid: ObjectId
    total: int
    unread: int
}

当我从“messages”集合中删除消息时,我还需要减少“counts”集合中的“total”,并且有条件地(如果“messages.isread”== false)减少“未读”字段。< / p>

为此,我需要首先检索消息,检查其“isread”字段,然后更新计数。在这些操作之间有可能将消息标记为已读取,然后我将错误地减少“未读”计数。

有没有办法根据一次拍摄的其他收藏结果有条件地改变一个集合中的某些内容?

5 个答案:

答案 0 :(得分:13)

这里有很多答案,但我想在这里填写所有空白:

  

有没有办法以原子方式更新MongoDB中的两个集合?

没有。两个集合的原子更新实际上是一个事务。 MongoDB不支持跨集合甚至集合内的事务。

MongoDB在单个文档上提供原子的several modifiers。因此,您可以一次增加几个不同的变量($inc)。虽然这里有一些限制,但您不能对单个属性执行两个不同的操作。

  

有没有办法根据一次拍摄的其他收藏结果有条件地改变一个集合中的某些内容?

atomic updates一般有一些文件。但是,您真正需要的是队列和某种形式的two-phase commit,或者您需要触发器。

触发器有not yet been implemented,所以在你的情况下它不是一个真正的选项。

  

有可能在这些操作之间将消息标记为已读取,然后我将错误地减少“未读”计数。

此时,您有几种不同的策略可以使这种行为具有一定程度的一致性。坦率地说,根据您的描述,您可能需要调查构建一个更新总计的简单队列。

答案 1 :(得分:4)

您无法在同一时刻从两个集合中删除文档。您可以做的是使用findAndModify()删除文档,以便在删除之前获得其确切的状态。这将解决您未读的计数问题。

答案 2 :(得分:1)

不,不幸的是,这是不可能的。 MongoDB仅支持单个文档范围内的atomic operations。没有办法在多个文档中执行事务操作,即使它们位于同一个集合中。

答案 3 :(得分:1)

MongoDB速度非常快,因此如果您的站点负载不高,您只需重新计算每个请求的消息总数和读取的消息总数。只在isread上放一个索引。即使在大量数据上,计数似乎也非常快。

事实上,您的总计和未读字段只是缓存。你真的需要吗?

这里有类似问题的问题:MongoDB: Calling Count() vs tracking counts in a collection

答案 4 :(得分:0)

您可以使用sql中的触发器执行此操作。但在蒙戈,没有触发器。

您可以对其中一个文档执行操作,并通过设置SafeMode.True

检查该操作的LastErrorMessage。

然后,如果没有错误,则更新第二个集合。

目前没有办法以原子方式做到这一点。

如果有,我会在我的项目中使用。我也需要这个功能。