MongoDBのfindAndModifyとupdateの違いは何ですか?


175

findAndModifyMongoDB のメソッドに少し混乱しています。updateメソッドに対するそれの利点は何ですか?私にとっては、最初にアイテムを返し、それを更新するだけのようです。しかし、なぜ最初に返品する必要があるのですか?私はMongoDBを読みました:決定的なガイドであり、キューを操作したり、get-and-setスタイルの原子性を必要とする他の操作を実行したりするのに便利だと書いています。しかし、それがこれをどのように達成するのか理解できませんでした。誰かがこれを私に説明できますか?

回答:


153

アイテムをフェッチしてから更新すると、これら2つのステップの間に別のスレッドによる更新が発生する可能性があります。最初にアイテムを更新してからフェッチすると、その間に別の更新があり、更新したものとは異なるアイテムが返されます。

「アトミック」に実行すると、更新しているアイテムとまったく同じアイテムが確実に返されます。つまり、その間に他の操作が発生することはありません。


6
まだ少し混乱しています。findAndModifyそれを妨害する他の更新操作がないことをどのように保証しますか?
chaonextdoor 2012年

78
@chaonextdoor findAndModifyは、操作の開始時にデータベースへのロックを取得するため、実行中の他の操作は処理できません。操作が完了すると、ロックが解除されます。
Lycha、2012年

4
findAndModifyは、リクエストの変更部分まで、実際にはロックを取得しません。したがって、複数のプロセスが同じレコードを更新できる可能性があります。
Mark Unsworth 2013年

5
@MarkUnsworthが10genでサポートケースを開きます-findAndModifyでのロックにバグがある場合は、エンジニアができるだけ早く修正することを保証できます。多くの人がこの動作を報告するのを見たとしても、それが当てはまる場合、findAndModifyは、それを使用しているほとんどすべての人のために設計されたように機能します-クライアント側のロジックまたは実装のバグに帰着していないように思われた場合、しかしもちろん、複雑なソフトウェアでは常にバグが存在する可能性があります。
Asya Kamsky 2013

4
@AsyaKamsky私はあなたと議論することを考えていましたが、それからあなたが正しいことに気づいたので、私は謝罪するべきだと思っています。ごめんなさい!
funkyeah

54

findAndModify ドキュメントを返しますが、更新は返しません。

Dwight Merriman(mongoDBの元の作者の1人)を正しく理解している場合、更新を使用して単一のドキュメントを変更するie( "multi":false}もアトミックです。現在、を使用して同等の更新を行うよりも高速ですfindAndModify


31

MongoDBドキュメントから(強調を追加):

  • デフォルトでは、両方の操作で1つのドキュメントが変更されます。ただし、multiオプションを指定したupdate()メソッドは、複数のドキュメントを変更できます

  • 複数のドキュメントが更新基準に一致する場合、findAndModify()で、ソート指定して、どのドキュメントを更新するかを制御する手段を提供できます。update()メソッドのデフォルトの動作では、複数のドキュメントが一致したときに更新する単一のドキュメントを指定できません。

  • デフォルトでは、findAndModify()メソッドドキュメントの変更前のバージョンを返します。更新されたドキュメントを取得するには、新しいオプションを使用します。update()メソッドは、操作のステータスを含むWriteResultオブジェクトを返します。更新されたドキュメントを返すには、find()メソッドを使用します。ただし、他の更新により、更新とドキュメントの取得の間でドキュメントが変更された可能性があります。また、更新によって単一のドキュメントのみが変更され、複数のドキュメントが一致した場合は、追加のロジックを使用して更新されたドキュメントを識別する必要があります。

  • MongoDB 3.2より前のバージョンでは、findAndModify()に書き込み関係を指定してデフォルトの書き込み関係をオーバーライドすることはできません、MongoDB 2.6以降はupdate()メソッドに書き込み関係指定できます

1つのドキュメントを変更する場合、findAndModify()メソッドとupdate()メソッドの両方がドキュメントをアトミックに更新します。


1
更新操作に対する書き込みの懸念を常に指定できます。さらに、3.2(技術的には3.1.1)以降、書き込みの懸念をfindAndModifyにも指定できます。jira.mongodb.org/browse/SERVER-6558
Asya

MongDB 3.6では、findAndModify()デフォルトで1つのドキュメントのみが変更されupdate()、1つ以上のドキュメントを更新できることがドキュメントに記載されていますが、を使用するarrayFiltersfindAndModify()すべての一致が更新されることがわかりました。多分それはバグですか?
WesternGun 2018

バグはありません-arrayFiltersを使用すると、複数の配列要素を更新できますが、それらはまだ単一のドキュメントにあります。
Asya Kamsky

10

ユースケースの1つの有用なクラスは、カウンターと同様のケースです。たとえば、次のコード(MongoDBテストの1つ)を見てみましょう: find_and_modify4.js

したがって、findAndModify1つのステップでカウンターを増分し、その増分値を取得します。比較:(A)この操作を2つのステップで実行し、他の誰か(B)がステップ間で同じ操作を行う場合、AとBは2つの異なる代わりに同じ最後のカウンター値を取得する可能性があります(考えられる問題の1つの例)。


0

カウンター操作(incまたはdec)および他の単一フィールドの変更ケースにはfindAndModify()を使用しました。アプリケーションをCouchbaseからMongoDBに移行したところ、GetAndlock()を実行するコードを置き換え、コンテンツをローカルで変更し、replace()を保存して、Get()を再度実行して、更新されたドキュメントをフェッチするこのAPIを見つけました。mongoDBでは、更新されたドキュメントを返すこの単一のAPIを使用しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.