我基本上会质疑“需要执行”您的发言,特别是考虑到缺乏{ multi: true }
你打算匹配和更新了大量的文件。
这里的第二个考虑是您提出的声明缺少任何类型的更新操作。这可能是你询问关于“差异”的问题的后果,但鉴于你目前对MongoDB查询操作与$and
的使用有明显的理解,那么我真的怀疑你“需要”这一点。
所以“如果”你真的需要写一份声明中这样的话,就应该是这样的:
myCollection.update(
{ "a": 1, "b": 1, "$isolated": true },
{ "$inc": { "c": 1 } },
{ "multi": true }
)
但你真的“需要”理解是什么,在做。
本质上这个查询会导致MongoDB持有一个“写入锁定”,并且至少在集合级别上。这样在整个wtite完成之前不能执行其他操作。这也确保了在此之前,所有读取尝试只会在进行任何更改之前看到文档的状态,直到该操作完全完成,然后后续读取看到所有更改。
这可能“听起来很诱人”,对某些人来说是个好主意,但实际上并非如此。写锁会影响更新的并发性,并且通常是一个不好的事情要避免。您也可能会将此与“事务”混淆,但事实并非如此,因此在执行过程中发生的任何故障只会在发生故障的位置暂停操作。这不会“撤消”在$isolated
区块内所做的更改,并且它们仍将保留。
差不多是唯一有效的使用案例在这里,那么,您可以“绝对需要”,所有元素被修改的匹配“A”和“B”,以保持事件一致的状态在运行这个操作的同时,某种组合正在“聚合”该组合。在那种情况下,然后暴露“部分”改变的“c”值可能不合意。但是,这种使用的范围相当渺茫,大多数通用应用程序不需要这种一致性。
回到$and
的用法,好吧,除非明确说明,否则无论如何所有的MongoDB参数都隐含地为$and
操作。 $and
唯一的一般用法是您需要对同一个文档键有多个条件。即使这样,也就是通常更好写在“右侧”的评价,如与$gt
和$lt
:
{ "a": { "$gt": 1, "$lt": 3 } }
作为完全一样:
{
"$and": [
{ "a": { "$gt": 1 } },
{ "b": { "$lt": 3 } }
]
}
所以它真的很多此一举。
最后,如果你真正想要做的是:
myCollection.update(
{ "a": 1, "b": 1 },
{ "$inc": { "c": 1 } },
)
更新一个单一的文件,那么就没有必要$isolated
可言。在这里获得一个明确的锁实际上只是提供了一个不需要的简单操作的复杂性。即使散装的,你可能真的不需要由获得锁提供的一致性,因此可以简单又做:
myCollection.update(
{ "a": 1, "b": 1 },
{ "$inc": { "c": 1 } },
{ "multi": true }
)
这将hapilly屈服,允许在所有选定的文件写入和读取“最新”信息。一般来说,“你想要这个”作为“原子”运算符(如$inc
)只是要修改它们看到的现值。
因此,在“多”写入在所有匹配中找到该文档之前,如果另一个进程与这些文档中的一个匹配,则无关紧要,因为无论如何都要执行“两个”$inc
操作。所有$isolated
在这里确实是“确保”,当这个操作开始时,那么“写入”写入将是“第一个”提交,然后在锁定期间尝试的任何事情将会发生在“之后”,而不仅仅是当每个操作都能够抓取该文件并进行修改时。
在9/10的情况下,最终结果是一样的。例外是在这里获得的“写入锁定”将“减慢”其他操作。
根据[文档](http://docs.mongodb.org/manual/reference/operator/update/isolated/),您将使用第一个变体。第二个似乎是不必要的复杂的做同样的事情。我不确定它是如何表现的,但是如果你有*因为某些原因使用了$和或其他操作符(在这里你不这样做),我认为*把$隔离在第一个层次上会更加正确。 '{$和:[.... stuff ...],$ isolated:true}' – Philipp