我想知道这2个查询之间的区别:
myCollection.update ( {
a:1,
b:1,
$isolated:1 } );
myCollection.update ( {
$and:
[
{a:1},
{b:1},
{$isolated:1}
] } );
基本上我需要为所有具有'a = 1和b = 1'的文档执行带有$ isolated的.update()。我对如何编写'$ isolated'参数以及如何确保查询正常工作感到困惑。
答案 0 :(得分:3)
我基本上会质疑"需要执行语句的#34; ,特别是考虑到你想要匹配和更新大量文档的{ multi: true }
的缺失。
这里的第二个考虑因素是你提出的陈述完全缺乏任何类型的更新操作。这可能是你问的关于"差异"的问题的一个后果,但鉴于你目前对与$and
的使用有关的MongoDB查询操作的明显理解,那么我严重怀疑你< em>&#34;需要&#34; 这一点。
所以&#34;如果&#34; 你真的需要用这种方式写一个语句,那么它应该是这样的:
myCollection.update(
{ "a": 1, "b": 1, "$isolated": true },
{ "$inc": { "c": 1 } },
{ "multi": true }
)
但你真正&#34;需要&#34; 才能理解这是在做什么。
本质上,这个查询将导致MongoDB保持&#34;写锁定&#34;,并且至少在集合级别上。因此,在整个wtite完成之前,不能执行任何其他操作。这也确保在此之前,所有读取尝试只会在进行任何更改之前看到文档的状态,直到该操作完全完成,然后后续读取才能看到所有更改。
对于某些人来说,这听起来很诱人,但实际上并非如此。写锁定会影响更新的并发性,通常是一件不可避免的事情。您可能也会将此与#34;交易相混淆。但事实并非如此,因此执行期间的任何失败只会在失败时暂停操作。这不会&#34;撤消&#34;在$isolated
块内进行的更改,它们将继续提交。
这里唯一有效的用例就是&#34;绝对需要&#34; ,所有要修改的元素匹配&# 34;&#34;和&#34; b&#34;如果事情是&#34;汇总&#34;以保持一致的状态。与此操作运行完全相同的组合。在那种情况下,然后暴露部分&#34;改变了&#34; c&#34;可能不合适。但是使用范围非常小,大多数通用应用程序都不需要这种一致性。
回到$and
的用法,所有MongoDB参数都是隐含的$and
操作,除非明确说明。 $and
的唯一一般用法是您需要在同一文档密钥上使用多个条件。即便如此,通常更好地写在&#34;右侧&#34;评估,例如$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 }
)
将允许写入所有选定的文件并读取&#34;最新的&#34;信息。一般来说,&#34;你想要这个&#34; 作为&#34; atomic&#34;像$inc
这样的运算符只会修改它们看到的当前值。
因此,在&#34; multi&#34;之前,另一个进程是否与其中一个文档相匹配并不重要。写在所有比赛中发现该文件,因为&#34;两者都是&#34;无论如何,$inc
操作都将执行。所有$isolated
确实在这里做的是&#34;确保&#34;当这个操作开始时,那么&#34;它&#34;&#34;写将是&#34;第一&#34;已经提交,然后锁定期间发生的任何事情都会发生在&#34;之后,而不是只是每个操作能够获取该文档并进行修改的一般顺序。
在9/10案例中,最终结果是相同的。唯一的例外是&#34;写锁定&#34;在这里获得,&#34;将&#34;放慢其他行动。