我对MongoDB中的findAndModify
方法有些困惑。相比于update
方法,它有什么优势?在我看来,它只是先返回项目,然后再更新它。但是,我为什么需要先返回该项目呢?我读过MongoDB权威指南,它说这个方法很好用,可以方便地操作队列和执行其他需要原子性的取值和赋值操作。但我不明白它是如何实现这一点的。有人能给我解释一下吗?
我对MongoDB中的findAndModify
方法有些困惑。相比于update
方法,它有什么优势?在我看来,它只是先返回项目,然后再更新它。但是,我为什么需要先返回该项目呢?我读过MongoDB权威指南,它说这个方法很好用,可以方便地操作队列和执行其他需要原子性的取值和赋值操作。但我不明白它是如何实现这一点的。有人能给我解释一下吗?
如果您获取一个项并更新它,那么在这两个步骤之间可能会有另一个线程进行更新。如果您先更新一个项然后再获取它,可能会有另一个更新在其中,并且您将收到与您更新的不同的项。
“原子方式”执行意味着您保证获得的是您正在更新的完全相同的项-即没有其他操作可以在其中发生。
findAndModify
返回文档,而update不会。
如果我正确理解了mongoDB的原始作者之一Dwight Merriman的话,使用update修改单个文档即("multi":false}也是原子操作。目前,使用update进行等价的更新应该比使用findAndModify
更快。
来自MongoDB文档(重点加粗):
默认情况下,这两种操作仅修改单个文档。但是,带有multi选项的update()方法可以修改多个文档。
如果多个文档符合更新条件,则对于findAndModify(),您可以指定排序以在一定程度上控制要更新的文档。 使用update()方法的默认行为时,在多个匹配文档时无法指定要更新的单个文档。
默认情况下,findAndModify()方法返回文档的修改前版本。要获取更新后的文档,请使用new选项。 update()方法返回包含操作状态的WriteResult对象。要返回更新后的文档,请使用find()方法。但是,其他更新可能已在您的更新和文档检索之间修改了该文档。此外,如果更新仅修改了一个文档,但多个文档匹配,则需要使用其他逻辑来标识更新的文档。
在MongoDB 3.2之前,您不能指定写关注findAndModify()以覆盖默认写关注,而您可以在MongoDB 2.6后的update()方法中指定写关注。
修改单个文档时,findAndModify()和update()方法都会以原子方式更新该文档。
findAndModify()
默认只修改一个文档,而update()
可以更新一个或多个文档,但当我使用arrayFilters
时,findAndModify()
会更新所有匹配项。也许这是一个bug? - WesternGun一个有用的用例类别是计数器和类似情况。例如,看一下这段代码(MongoDB测试之一):find_and_modify4.js。
因此,使用 findAndModify
一步完成计数器递增并获取递增后的值。相比之下:如果您(A)在两个步骤中执行此操作,而其他人(B)在您的步骤之间执行相同的操作,则 A 和 B 可能会获得相同的最后一个计数器值,而不是两个不同的值(这只是可能出现问题的一个例子)。
findAndModify
和 update
都执行单个请求内的原子更改,例如增加计数器;实际上,<query>
和 <update>
参数在很大程度上是相同的没有系统级别的写锁或信号量可以由用户获得。 MongoDB故意不让用户轻松地检出文档,然后更改它,然后将其写回,同时防止其他人在此期间更改该文档。(虽然开发人员可能认为他们想要那样做,但从可扩展性和并发性的角度来看,这通常是反模式... 作为一个简单的例子,想象一下客户端获取写锁,然后在持有锁期间被杀死。如果您真的需要写锁,则可以在文档中创建一个并使用原子更改来比较和设置它,然后确定自己的恢复过程以处理遗弃的锁等。但是,如果您走这条路,请小心。)
据我所知,这些方法的两个主要区别为:
findAndModify
允许此操作,默认返回原始记录,或者可以返回更新后的new
记录;而使用 update
只能得到 WriteResult
,而在读取或更新之前立即读取文档无法防止其他进程同时更改记录findAndModify
仅更改其中一个,并允许您自定义sort
以指示应更改哪一个;update
可以更改所有的记录(默认情况下只更改一个),但不能告诉您要更改哪一条因此,在 HungryCoder 所说的情况下,update
更有效率,如果您可以接受其限制(例如,您不需要读取文档;或者当然,如果您正在更改多个记录)。但是对于许多原子更新,您确实需要文档,并且在这种情况下就需要 findAndModify
。
findAndModify
如何保证没有其他更新操作干扰它? - chaonextdoor