2011-05-22 58 views
15

我有消息的集合:有什么办法可以自动更新MongoDB中的两个集合?

{ 
    userid: ObjectId 
    total: int 
    unread: int 
} 

当我删除“邮件”收藏,我也需要减少“总的消息:

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

和消息的集合,每个用户计数“在”计数“集合中,并且有条件地(如果”messages.isread“== false)减少”未读“字段。

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

有没有一种方法可以根据一次拍摄中的其他收集结果有条件地更改某个收藏集中的某些内容?

回答

11

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

有什么办法可以以原子更新MongoDB中的两个集合?

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

MongoDB提供several modifiers,它们在单个文档上是原子的。所以你可以一次增加几个不同的变量($inc)。尽管这里有一些限制,但您无法对单个属性执行两种不同的操作。

有没有办法在一个镜头中基于其他集合的结果有条件地更改某个集合中的某些内容?

这里有一些关于atomic updates的文档。然而,你真正需要的是一个队列和某种形式的two-phase commit或者你需要触发器。

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

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

在这一点上,你有几个不同的策略,使其具有一定程度的一致性。坦率地说,根据你的描述,你可能想调查建立一个简单的队列来更新你的总数。

0

你可以用sql中的触发器来做到这一点。但在蒙戈中,没有触发器。

您可以在文档中的一个进行操作,并通过设置SafeMode.True

然后,如果没有错误,则更新第二集中检查LastErrorMessage上操作。

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

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

1

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

4

您无法在同一时刻从两个集合中删除文档。你可以做的是使用findAndModify()去除文档,以便在删除之前得到它的确切状态。这会照顾你的未读数问题。

1

MongoDB速度非常快,所以如果你的网站负载不高,你可以简单地重新计算消息的总数和在每个请求上读取的消息总数。只有在读取索引。计数似乎非常快,即使是大量的数据。

实际上,您的总和未读字段仅仅是缓存。你真的需要它吗?

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

+0

这也是我的问题:)我的网站会有相当高的负载,而且我不想在每次需要时重新计算统计数据,所以我使用的是计数器集合。 – Andrey 2011-05-23 19:55:11

+0

如果您尚未这样做,则应该对其进行配置。 – Maxence 2011-05-24 07:12:47

+0

即使没有分析,我可以说cursor.count()总是比检索一个数字慢得多,特别是在具有数亿条记录的集合上。 – Andrey 2011-05-24 11:57:37

相关问题