2012-05-09 61 views
4

模式:MongoDB中更新多个文档

{ 
    name: String, 
    available: Boolean, 
    for: String 
} 

有 “一”:

{ 
    name: "a", 
    available: true, 
    for: ["b", "c"] 
} 

和 “b”:

{ 
    name: "b", 
    available: true, 
    for: ["a", "b] 
} 

如果我更新a.available =假,我应该同时更新b.available = false。 我怎么能更新两个文件,并确保在更新“a”和“b”之间不会有其他进程/线程获得“b”。

回答

5

MongoDB不支持原子事务。因此,如果您需要在第二次更新失败时进行第一次更新“自行撤消”,那么您的运气不佳。

但是,在某些有限的情况下,MongoDB确实支持隔离更新。更新不是全部或没有,但MongoDB将保证没有其他人在写入过程中写入集合。

一对夫妇的主要注意事项:

  • 的文件都必须是同一个集合
  • 的更新都必须在一个查询

基于这个例子中你可以指定在已经提供,你的情况可能有资格。

Here是描述孤立更新的文档。

基本上你会想发出类似下面以原子设置为“可用”,以虚假的更新操作时,名称是“A”或“B”:

db.blah.update({"name": {"$in": ["a", "b"]}, "$atomic": 1}, {"available": false}); 
+0

如果我想用不同的值自动更新不同的文档。如果name ==“a”,则更新计数= 1;如果name ==“b”,则更新计数= 2。 – Kevin

+0

这可能不可能。正如我所说的,这个功能有一些重大的限制 - MongoDB并不是真正为此设计的。 –

3

如果你真的需要它,可以在mongodb之上实现这个逻辑(在你的应用程序中或在mongo驱动程序的包装器中更好)。

您要求隔离属性。一种方法是通过使用MVCC模式。这真是太过于夸张了,但这是为了让你知道如果你真的需要mongodb和一些ACID属性你可以做什么。

MVCC模式的通用实现描述here。在github上也有一个project来实现这个,但它是一个java项目。

您可能还会看到这SO question和他们的答案。我现在的答案只是它的一个总结。