MongoDB とドライバー
定義
互換性
このメソッドは、次の環境でホストされている配置で使用できます。
- MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud
注意
This command is supported in all MongoDB Atlas clusters. For information on Atlas support for all commands, see Unsupported Commands.
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
バージョン5.0で変更。
db.collection.findAndModify() の形式は次のとおりです。
db.collection.findAndModify({ query: <document>, sort: <document>, remove: <boolean>, update: <document or aggregation pipeline>, new: <boolean>, fields: <document>, upsert: <boolean>, bypassDocumentValidation: <boolean>, writeConcern: <document>, maxTimeMS: <integer>, collation: <document>, arrayFilters: [ <filterdocument1>, ... ], let: <document> // Added in MongoDB 5.0 });
パラメーター
db.collection.findAndModify() 次の埋め込みドキュメント フィールドを持つドキュメント パラメータを受け取ります。
Parameter | タイプ | 説明 | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ドキュメント | 任意.変更の選択基準。フィールドでは、 指定しない場合、デフォルトは空のドキュメントになります。 クエリ引数がドキュメントでない場合、操作はエラーになります。 | ||||||||||||||||||
| ドキュメント | 任意。クエリで複数のドキュメントが選択された場合に、その操作で更新するドキュメントを決定します。 ソート引数がドキュメントでない場合、操作はエラーになります。 MongoDB では、コレクション内のドキュメントを特定の順序で保存することはありません。重複する値を含むフィールドでソートする場合、それらの値を含むドキュメントは任意の順序で返されます。
ソート条件で指定されたフィールドが2つのドキュメントに存在しない場合、それらがソートされる値は同じです。2つのドキュメントは、任意の順序で返される可能性があります。 一貫したソート順序が必要な場合は、一意の値を含むフィールドを少なくとも 1 つ含めてソートしてください。これを保証する最も簡単な方法は、 詳細については、「ソートの整合性」を参照してください。 | ||||||||||||||||||
| ブール値 |
| ||||||||||||||||||
| ドキュメントまたは配列 |
| ||||||||||||||||||
| ブール値 | 任意。 | ||||||||||||||||||
| ドキュメント | 任意。返すフィールドのサブセット。
For more information on projection, see | ||||||||||||||||||
| ブール値 | 任意。 When
複数のアップサートを回避するため、 デフォルトは | ||||||||||||||||||
| ブール値 | 任意. | ||||||||||||||||||
| ドキュメント | 任意。書込み保証(write concern)を表現するドキュメント。デフォルトの書込み保証を使用する場合は省略します。 トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。 | ||||||||||||||||||
| non-negative integer | 任意。 時間制限をミリ秒単位で指定します。 MongoDB は、 | ||||||||||||||||||
| ドキュメント | 任意。 任意。操作に使用する照合を指定します。 照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。 照合オプションの構文は次のとおりです。 照合を指定する場合、 照合が指定されていなくても、コレクションにデフォルトの照合が設定されている場合( コレクションにも操作にも照合が指定されていない場合、MongoDB では以前のバージョンで使用されていた単純なバイナリ比較によって文字列が比較されます。 1 つの操作に複数の照合は指定できません。たとえば、フィールドごとに異なる照合を指定できません。また、ソートと検索を一度に実行する場合、検索とソートで別の照合を使用できません。 | ||||||||||||||||||
| 配列 | 任意。配列フィールドの更新操作でどの配列要素を変更するかを決定するフィルター ドキュメントの配列。 アップデート ドキュメントでは、
アップデート ドキュメントには同じ識別子を複数回含めることができます。ただし、アップデート ドキュメント内の個別の識別子 ( ただし、次の例のように、単一のフィルター ドキュメント内の同じ識別子に複合条件を指定できます。 For examples, see Specify
| ||||||||||||||||||
ドキュメント | 任意。 変数のリストを含むドキュメントを指定します。これにより、変数をクエリテキストから分離することで、コマンドの読みやすさを向上させることができます。 ドキュメントの構文は次のとおりです。 変数は式によって返された値に設定され、その後は変更できません。 コマンド内の変数の値にアクセスするには、二重ドル記号の接頭辞( 結果のフィルタリングに変数を使用するには、 For a complete example using バージョン 5.0 の新機能。 |
Return Data
除く操作では、クエリがドキュメントと一致する場合、findAndModify() は除かれたドキュメントを返します。クエリが除くドキュメントと一致しない場合、findAndModify() は null を返します。
更新操作の場合、findAndModify()は次のいずれかを返します。
newパラメーターがセットされていないか、falseの場合クエリがドキュメントにマッチした場合、変更前のドキュメント。
それ以外の場合は、
null。
newがtrueの場合クエリが一致を返した場合、更新されたドキュメント。
upsert: trueでクエリに一致するドキュメントがない場合、挿入されたドキュメント。それ以外の場合は、
null。
動作
パフォーマンス
再試行可能な書き込みでは、更新を実行する前に、findAndModify() メソッドを使用してドキュメント全体をレプリカセット内の各ノードの特別なサイドコレクションにコピーする必要があります。そのため、大きな文書や大きなレプリカセットを扱う場合、findAndModify() はコストが大きい操作になる可能性があります。
バージョン 8.0 の新機能:
ユーザー定義の順序付けで最初のドキュメントをより優れたパフォーマンスで更新するため、sort オプションを指定した db.collection.updateOne() メソッドを使用します。
fields プロジェクション
重要
言語の整合性
As part of making find() and findAndModify() projection consistent with aggregation's $project stage,
The
find()andfindAndModify()projection can accept aggregation expressions and syntax.MongoDB は、プロジェクションに関して追加の制限を適用します。詳細については、「プロジェクションの制限」を参照してください。
fieldsオプションは次のような形式のドキュメントを取ります:
{ field1: <value>, field2: <value> ... }
プロジェクション | 説明 |
|---|---|
| フィールドを包含することを指定します。プロジェクションの値としてゼロ以外の整数を指定した場合、その値を |
| フィールドの除外を指定します。 |
| |
| 配列プロジェクション 演算子( ビューには使用できません。 |
| プロジェクションを行ったフィールドの値を指定します。 集計式と構文の使用(リテラルと集計変数の使用を含む)では、新しいフィールドをプロジェクションしたり、既存のフィールドを新しい値でプロジェクションしたりできます。
|
埋め込みフィールド仕様
埋め込みドキュメント内のフィールドの場合は、次のいずれかを使用してフィールドを指定できます。
ドット表記の場合は次のようになります。
"field.nestedfield": <value>ネストされた形式の例
{ field: { nestedfield: <value> } }
_id フィールドプロジェクション
_id フィールドは、プロジェクションで _id: 0 を明示的に指定して抑制しない限り、返されるドキュメントにデフォルトで含まれます。
包含または除外
projection には、 _id フィールドを除いて、包含指定と除外指定の両方を含めることはできません。
フィールドを明示的に含めるプロジェクションでは、
_idフィールドだけが明示的に除外できる唯一のフィールドです。フィールドを明示的に除外するプロジェクションでは、
_idフィールドが明示的に包含できる唯一のフィールドですが、デフォルトで_idフィールドが含まれます。
一意なインデックスを使用したアップサート
重複を防ぐためのユニークインデックスがない限り、アップサートによって重複したドキュメントが作成されることがあります。
Andy という名前のドキュメントが存在せず、複数のクライアントがほぼ同時に次のコマンドを発行する例を考えます。
db.people.findAndModify( { query: { name: "Andy" }, update: { $inc: { score: 1 } }, upsert: true } )
クライアントがデータを正常に挿入する前にすべてのfindOneAndUpdate()操作がクエリ フェーズを終了し、かつnameフィールドに一意なインデックスがない場合、各findOneAndUpdate()操作によって挿入が行われ、name: Andyを含む複数のドキュメントが作成される可能性があります。
name フィールドに一意なインデックスを設定すると、ドキュメントが 1 つだけ作成されるようになります。一意なインデックスが設定されると、複数のfindOneAndUpdate()操作で次の動作が見られるようになります。
正確に 1 回の
findOneAndUpdate()操作で新しいドキュメントが正常に挿入されます。その他の
findOneAndUpdate()操作は、新しく挿入されたドキュメントを更新するか、一意なキーの競合が原因で失敗します。他の
findOneAndUpdate()操作で新しく挿入されたドキュメントを更新するには、次の条件がすべて満たされている必要があります。ターゲット コレクションに一意なインデックスがあるため、重複キー エラーが発生。
更新操作が
updateManyではない、またはmultiがfalse。アップデートの一致条件は、次のいずれかです。
単一の等価述語。例:
{ "fieldA" : "valueA" }等価述語の論理 AND。例:
{ "fieldA" : "valueA", "fieldB" : "valueB" }
等価述語内のフィールドが、一意なインデックス キー パターン内のフィールドと一致。
更新操作が、一意なインデックス キー パターン内のフィールドを変更しない。
次の表に示す upsert 操作の例では、キーの衝突が発生した場合に更新されるか失敗します。
ユニークインデックスキーのパターン | アップデート操作 | 結果 | ||||||
|---|---|---|---|---|---|---|---|---|
| | マッチしたドキュメントの | ||||||
| | 一意なインデックス キー パターン( | ||||||
| | 等式述語フィールド( |
シャーディングされたコレクション
シャーディングされたコレクションでfindAndModifyを使用するには、
1つのシャードのみをターゲットにする場合は、
queryフィールドで部分的なシャードキーを使用できます。またはqueryフィールドの完全なシャードキーに等価条件を指定できます。バージョン7.1以降では、クエリ仕様でシャードキーまたは
_idフィールドを指定する必要がありません。
シャーディングされたコレクション内のドキュメントには、シャードキー フィールドがない場合があります。シャードキーがないドキュメントを対象とするには、null の等価一致を別のフィルター条件(_id フィールド上と同様に)と組み合わせて使用できます。例:
{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
シャードキーの変更
シャードキー フィールドが不変の _id フィールドでない限り、ドキュメントのシャードキー値を更新できます。
警告
シャーディングされたコレクション内のドキュメントには、シャード キー フィールドがないことがあります。ドキュメントのシャード キーの値を変更するときに、誤ってシャード キーを削除しないように注意してください。
既存のシャードキー値をfindAndModify() で更新する方法:
必ず
mongos上で使用します。シャードに直接操作を実行しないでください。トランザクション内で、または 再試行可能な書き込みとして実行する必要があります。
完全なシャードキーに等価フィルターを含める必要があります。
欠落しているシャードキー
Documents in a sharded collection can be missing the shard key fields. To use db.collection.findAndModify() to set the document's missing shard key:
必ず
mongos上で使用します。シャードに直接操作を実行しないでください。新しいシャードキー値が
nullでない場合は、トランザクション内で実行するか、再試行可能な書き込みとして実行する必要があります。完全なシャードキーに等価フィルターを含める必要があります。
Tip
欠落しているキー値は NULL 等価一致の一部として返されるため、NULL 値のキーが更新されないように、必要に応じて追加のクエリ条件(_id フィールドなど)を追加します。
スキーマ検証
The db.collection.findAndModify() method adds support for the bypassDocumentValidation option, which lets you bypass schema validation when inserting or updating documents in a collection with validation rules.
update メソッドとの比較
ドキュメントを更新する場合の findAndModify() メソッドと updateOne() メソッドの動作は異なります。
更新条件に一致するドキュメントが複数ある場合、
findAndModify()では、sortを指定することで、更新するドキュメントの選択に関して一定の制御が可能です。updateOne()は一致する最初のドキュメントを更新します。デフォルトでは、
findAndModify()はドキュメントの変更前のバージョンを返します。更新されたドキュメントを取得するには、newオプションを使用します。updateOne()メソッドは、操作のステータスを含むWriteResult()オブジェクトを返します。更新されたドキュメントを返すには、
find()メソッドを使用します。ただし、更新してからドキュメントを取得するまでの間に、他の更新によってドキュメントが変更される可能性があります。また、更新によって 1 つのドキュメントのみが変更されたが、複数のドキュメントが一致した場合は、更新されたドキュメントを識別するために追加のロジックを使用する必要があります。
1 つのドキュメントを変更する場合、findAndModify()メソッドと updateOne() メソッドの両方でドキュメントがアトミックに更新されます。これらのメソッドの相互作用と操作順序の詳細については、 「アトミック性とトランザクション」を参照してください。
トランザクション
findAndModify() は分散トランザクション内で使用できます。
重要
ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。
トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。
トランザクション内のアップサート
トランザクションがクロスシャード間書き込みトランザクション(write transaction)でない場合に、分散トランザクション内にコレクションとインデックスを作成できます。
findAndModify() upsert: true は、既存のコレクションまたは存在しないコレクションで実行できます。存在しないコレクションで実行すると、操作によってコレクションが作成されます。
書込み保証とトランザクション
トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。
Oplog エントリ
findAndModify()操作によってドキュメントが正常に検出され、変更された場合、その操作によってoplog(操作ログ)にエントリが追加されます。操作が失敗した場合、または更新するドキュメントが見つからなかった場合は、その操作によって oplog にエントリーが追加されることはありません。
書込み保証 (write concern) エラー
6.0 より前のバージョンの MongoDB では、シャーディングされたクラスターで findAndModify コマンドが実行され、シャード応答にエラーが含まれている場合、mongos は writeConcernError ドキュメントを破棄します。MongoDB 6.0 以降では、mongos は writeConcernError を返します。
例
更新と返却
次のメソッドは、クエリの条件に一致するドキュメントの people コレクション内の既存のドキュメントを更新して返します。
db.people.findAndModify({ query: { name: "Tom", state: "active", rating: { $gt: 10 } }, sort: { rating: 1 }, update: { $inc: { score: 1 } } })
このメソッドは、次のアクションを実行します。
queryは、nameフィールドの値がTom、stateフィールドの値がactive、ratingフィールドの値がgreater than10 であるドキュメントをpeopleコレクション内で検索します。sortは、クエリの結果を昇順に並べます。複数のドキュメントがquery条件を満たす場合、メソッドはこのsortの順序に従って最初のドキュメントを変更対象として選択します。incrementsにより、scoreフィールドの値が 1 だけ更新されます。このメソッドは元の(つまり 変更前の)このアップデート用に選択されたドキュメントを返します。
{ "_id" : ObjectId("50f1e2c99beb36a0f45c6453"), "name" : "Tom", "state" : "active", "rating" : 100, "score" : 5 } 更新されたドキュメントを返すには、メソッドに
new:trueオプションを追加します。query条件に一致するドキュメントがない場合、メソッドはnullを返します。
アップサート
次のメソッドには、update操作にupsert: trueのオプションが含まれおり、一致するドキュメントをアップデートするか、一致するドキュメントが存在しない場合は新しいドキュメントを作成します。
db.people.findAndModify({ query: { name: "Gus", state: "active", rating: 100 }, sort: { rating: 1 }, update: { $inc: { score: 1 } }, upsert: true })
一致するドキュメントが見つかった場合、更新を実行します。
メソッドが一致するドキュメントを見つけられない場合、メソッドは新しいドキュメントを作成します。このメソッドには sort オプションが含まれていたため、元の(変更前の)ドキュメントとして空のドキュメント { } が返されます。
{ }
メソッドに sort オプションが含まれていない場合、メソッドは null を返します。
null
新しいドキュメントの返却
次のメソッドには、 upsert: trueオプションとnew:trueオプションの両方が含まれています。このメソッドは、一致するドキュメントを更新して更新されたドキュメントを返すか、一致するドキュメントが存在しない場合はドキュメントを挿入して value フィールドに新しく挿入されたドキュメントを返します。
次の例では、people コレクション内のどのドキュメントも query 条件に一致しません。
db.people.findAndModify({ query: { name: "Pascal", state: "active", rating: 25 }, sort: { rating: 1 }, update: { $inc: { score: 1 } }, upsert: true, new: true })
このメソッドは、新しく挿入されたドキュメントを返します。
{ "_id" : ObjectId("50f49ad6444c11ac2448a5d6"), "name" : "Pascal", "rating" : 25, "score" : 1, "state" : "active" }
並べ替えと削除
次の例では、rating フィールドに sort 仕様を含めることで、state の値が active であり、一致するドキュメントの中で最も rating が低い 1 つのドキュメントを people コレクションから削除します。
db.people.findAndModify( { query: { state: "active" }, sort: { rating: 1 }, remove: true } )
このメソッドは、削除されたドキュメントを返します。
{ "_id" : ObjectId("52fba867ab5fdca1299674ad"), "name" : "XYZ123", "score" : 1, "state" : "active", "rating" : 3 }
照合の指定
照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。
コレクション myCollは、次のドキュメントを含みます。
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
次の操作には照合オプションが含まれます。
db.myColl.findAndModify({ query: { category: "cafe", status: "a" }, sort: { category: 1 }, update: { $set: { status: "Updated" } }, collation: { locale: "fr", strength: 1 } });
この操作を実行すると次のドキュメントが返されます。
{ "_id" : 1, "category" : "café", "status" : "A" }
配列更新操作での arrayFilters の指定
注意
arrayFilters は、集計パイプラインが使用される更新では使用できません。
配列フィールドを更新するときに、どの配列要素を更新するかを決定するためのarrayFiltersを指定できます。
arrayFilters 条件に一致する要素を更新する
注意
arrayFilters は、集計パイプラインが使用される更新では使用できません。
次のドキュメントを使用してコレクション students を作成します。
db.students.insertMany( [ { "_id" : 1, "grades" : [ 95, 92, 90 ] }, { "_id" : 2, "grades" : [ 98, 100, 102 ] }, { "_id" : 3, "grades" : [ 95, 110, 100 ] } ] )
To update all elements that are greater than or equal to 100 in the grades array, use the filtered positional operator $[<identifier>] with the arrayFilters option in the db.collection.findAndModify() method:
db.students.findAndModify({ query: { grades: { $gte: 100 } }, update: { $set: { "grades.$[element]" : 100 } }, arrayFilters: [ { "element": { $gte: 100 } } ] })
この操作により 1 つのドキュメントの grades フィールドが更新され、操作後にコレクションには次のドキュメントが含まれます。
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 100 ] } { "_id" : 3, "grades" : [ 95, 110, 100 ] }
ドキュメントの配列の特定の要素を更新する
注意
arrayFilters は、集計パイプラインが使用される更新では使用できません。
次のドキュメントを使用してコレクション students2 を作成します。
db.students2.insertMany( [ { "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ] }, { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] } ] )
次の操作では、_id フィールドが 1 に等しいドキュメントを検索し、フィルター処理された位置演算子 $[<identifier>] を arrayFilters とともに使用して、grades 配列内で grade が 85 以上の全要素の mean を更新します。
db.students2.findAndModify({ query: { _id : 1 }, update: { $set: { "grades.$[elem].mean" : 100 } }, arrayFilters: [ { "elem.grade": { $gte: 85 } } ] })
この操作により 1 つのドキュメントの grades フィールドが更新され、操作後にコレクションには次のドキュメントが含まれます。
{ "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 100, "std" : 4 }, { "grade" : 85, "mean" : 100, "std" : 6 } ] } { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] }
更新に集計パイプラインを使用
db.collection.findAndModify() は、更新の集計パイプラインを受け入れることができます。このパイプラインには次のステージが含まれる可能性があります。
$addFieldsおよびそのエイリアス$set$replaceRootおよびそのエイリアス$replaceWith
集計パイプラインを使用すると、現在のフィールド値に基づいて条件付きのアップデートを表現したり、あるフィールドを他のフィールドの値を使用してアップデートするなど、より表現内容の多いアップデート ステートメントが可能になります。
たとえば、次のドキュメントを含むコレクション students2 を作成します。
db.students2.insertMany( [ { "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ] }, { "_id" : 2, "grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85, "std" : 4 } ] } ] )
次の操作では、_id フィールドが 1 に等しいドキュメントを検索し、集計パイプラインを使用して grades フィールドから新しいフィールド total を計算します。
db.students2.findAndModify( { query: { "_id" : 1 }, update: [ { $set: { "total" : { $sum: "$grades.grade" } } } ], // The $set stage is an alias for ``$addFields`` stage new: true } )
この操作は更新されたドキュメントを返します。
{ "_id" : 1, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" : 85, "std" : 6 } ], "total" : 250 }
変数の使用 let
バージョン 5.0 の新機能。
コマンド内の他の場所からアクセスできる変数を定義するには、 letオプションを使用します。
注意
変数を使用して結果をフィルタリングするには、$expr 演算子内の変数にアクセスする必要があります。
コレクション cakeFlavors を以下ように作成します。
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
次の例では、let に targetFlavor 変数を定義し、その変数を使用してケーキのフレーバーをチェリーからオレンジに変更します。
db.cakeFlavors.findAndModify( { query: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, update: { flavor: "orange" }, let: { targetFlavor: "cherry" } } )
ユーザーロールとドキュメントの更新
MongoDB 7.0 以降では、新しい USER_ROLES システム変数を使用してユーザー ロールを返すことができます。
このセクションの例では、医療情報を含むコレクション内のフィールドの更新を示します。この例では、USER_ROLES システム変数から現在のユーザー ロールを読み取り、ユーザーが特定のロールを持っている場合にのみ更新を実行します。
システム変数を使用するには、変数名の先頭に $$ を追加します。システム変数 USER_ROLES を $$USER_ROLES として指定します。
この例では、次のユーザーを作成します。
JamesBillingロールの使用MichelleProviderロールの使用
ロール、ユーザー、コレクションを作成するには、次の手順を実行します。
ロールの作成
必要な権限とリソースを持つ Billing および Provider という名前のロールを作成します。
実行:
db.createRole( { role: "Billing", privileges: [ { resource: { db: "test", collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } ) db.createRole( { role: "Provider", privileges: [ { resource: { db: "test", collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
Provider ロールを持つ Michelle としてログインし、更新を実行します。
更新の実行
実行:
// Attempt to find and modify document db.medical.findAndModify( { query: { $and: [ { // Only update the document for Mary Smith patientName: { $eq: "Mary Smith" } }, { // User must have the Provider role to perform the update $expr: { $ne: [ { $setIntersection: [ [ "Provider" ], "$$USER_ROLES.role" ] }, [] ] } } ] }, // Update document update: { patientName: "Mary Smith", diagnosisCode: "ACH 03", creditCard: "6541-7534-9637-3456" } } )
前の例では、$setIntersection を使用して、"Provider" s文字列と $$USER_ROLES.role のユーザー ロールの共通部分が空ではないドキュメントを返します。Michelle はProvider のロールを持つので、更新が実行されます。
次に、Provider ロールを持たない James としてログインし、同じ更新の実行を試みます。
更新の試行
実行:
// Attempt to find and modify document db.medical.findAndModify( { query: { $and: [ { // Only update the document for Mary Smith patientName: { $eq: "Mary Smith" } }, { // User must have the Provider role to perform the update $expr: { $ne: [ { $setIntersection: [ [ "Provider" ], "$$USER_ROLES.role" ] }, [] ] } } ] }, // Update document update: { patientName: "Mary Smith", diagnosisCode: "ACH 03", creditCard: "6541-7534-9637-3456" } } )
前の例では、ドキュメントは更新されません。