AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。
Docs Menu

findAndModify(データベースコマンド)

findAndModify

1 つのドキュメントを更新して返します。デフォルトでは、返されるドキュメントには更新によって行われた変更は含まれません。変更されたドキュメントを返すには、new オプションを使用します。

Tip

In mongosh, this command can also be run through the db.collection.findAndModify() helper method.

Helper methods are convenient for mongosh users, but they may not return the same level of information as database commands. In cases where the convenience is not needed or the additional return fields are required, use the database command.

このコマンドは、次の環境でホストされている配置で使用できます。

  • MongoDB Atlas はクラウドでの MongoDB 配置のための完全管理サービスです

注意

このコマンドは、すべての MongoDB Atlas クラスターでサポートされています。すべてのコマンドに対する Atlas のサポートについては、「サポートされていないコマンド」を参照してください。

  • MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン

  • MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン

バージョン5.0で変更。

このコマンドの構文は、次のとおりです。

db.runCommand(
{
findAndModify: <collection-name>,
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: <array>,
hint: <document|string>,
comment: <any>,
let: <document> // Added in MongoDB 5.0
}
)

このコマンドは、次のフィールドを使用します。

フィールド
タイプ
説明

query

ドキュメント

Optional. The selection criteria for the modification. The query field employs the same query selectors as used in the db.collection.find() method. Although the query may match multiple documents, findAndModify selects only one document to update.

指定しない場合、デフォルトは空のドキュメントになります。

クエリ引数がドキュメントでない場合、操作はエラーになります。

sort

ドキュメント

Optional. Determines which document the operation updates if the query selects multiple documents. findAndModify updates the first document in the sort order specified by this argument.

ソート引数がドキュメントでない場合、操作はエラーになります。

MongoDB では、コレクション内のドキュメントを特定の順序で保存することはありません。重複する値を含むフィールドでソートする場合、それらの値を含むドキュメントは任意の順序で返されます。

一貫したソート順序が必要な場合は、一意の値を含むフィールドを少なくとも 1 つ含めてソートしてください。これを保証する最も簡単な方法は、_idフィールドをソートのクエリに含めることです。

詳細については、「ソートの整合性」を参照してください。

remove

ブール値

remove フィールドまたは update フィールドのいずれかを指定する必要があります。query フィールドで指定されたドキュメントを削除します。選択したドキュメントを削除するには、これを true に設定します。デフォルト値は false です。

update

ドキュメントまたは配列

remove フィールドまたは update フィールドのいずれかを指定する必要があります。選択したドキュメントの更新を実行します。

new

ブール値

任意。true の場合、元のドキュメントではなく更新されたドキュメントを返します。デフォルト値は false です。

fields

ドキュメント

任意。返すフィールドのサブセット。fields ドキュメントでは、fields: { <field1>: 1, <field2>: 1, ... } のように 1 を含むフィールドを含めることを指定しています。「プロジェクション」を参照してください。

フィールド引数がドキュメントでない場合、操作はエラーになります。

upsert

ブール値

任意。update フィールドと組み合わせて使用します。

When true, findAndModify either:

  • query に一致するドキュメントがない場合は、新しいドキュメントを作成します。詳しくは、「アップサートの動作」を参照してください。

  • query に一致する 1 つのドキュメントをアップデートします。

複数のアップサートを回避するため、query フィールドにユニークインデックスが付けられていることを確認します。例については、「ユニークインデックスを使用したアップサート」を参照してください。

デフォルトは false で、一致するものが見つからなくても新しいドキュメントは挿入されません

bypassDocumentValidation

ブール値

Optional. Enables findAndModify to bypass schema validation during the operation. This lets you update documents that do not meet the validation requirements.

writeConcern

ドキュメント

任意.書込み保証 (write concern) を指定します。デフォルトの書込み保証 (write concern) を使用する場合は省略します。

トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。

maxTimeMS

non-negative integer

任意。

時間制限をミリ秒単位で指定します。maxTimeMS の値を指定しない場合、操作はタイムアウトしません。値を 0 にすると、デフォルトの無制限動作を明示的に指定します。

MongoDB は、db.killOp() と同じメカニズムを使用して、割り当てられた時間制限を超えた操作を終了します。MongoDB は、指定された割り込みポイントのいずれかでのみ操作を終了します。

findAndModify

string

コマンドを実行するコレクション。

collation

ドキュメント

任意。

任意。操作に使用する照合を指定します。

照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。

照合オプションの構文は次のとおりです。

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

照合を指定する場合、locale フィールドは必須ですが、その他の照合フィールドはすべて任意です。フィールドの説明については、照合ドキュメントを参照してください。

照合が指定されていなくても、コレクションにデフォルトの照合が設定されている場合(db.createCollection() を参照)には、コレクションの照合が使用されます。

コレクションにも操作にも照合が指定されていない場合、MongoDB では以前のバージョンで使用されていた単純なバイナリ比較によって文字列が比較されます。

1 つの操作に複数の照合は指定できません。たとえば、フィールドごとに異なる照合を指定できません。また、ソートと検索を一度に実行する場合、検索とソートで別の照合を使用できません。

arrayFilters

配列

任意。配列フィールドの更新操作でどの配列要素を変更するかを決定するフィルター ドキュメントの配列。

アップデート ドキュメントでは、$[<identifier>] フィルター処理された位置演算子を使用して識別子を定義し、配列フィルター ドキュメントで参照します。識別子がアップデートドキュメントに含まれていない場合、識別子の配列フィルタードキュメントを作成することはできません。

<identifier>は小文字で始まり、含めることができるのは英数字のみです。

アップデート ドキュメントには同じ識別子を複数回含めることができます。ただし、アップデート ドキュメント内の個別の識別子 ($[identifier]) それぞれに対し、対応する配列フィルター ドキュメントを 1 つだけ指定する必要があります。つまり、同じ識別子に対して複数の配列フィルター ドキュメントを指定することはできません。たとえば、アップデート ステートメントに識別子 x が(場合によっては複数回)含まれている場合、x に 2 つの個別のフィルタ ドキュメントを含む arrayFilters に対して、次のように指定することはできません。

// INVALID
[
{ "x.a": { $gt: 85 } },
{ "x.b": { $gt: 80 } }
]

ただし、次の例のように、単一のフィルター ドキュメント内の同じ識別子に複合条件を指定できます。

// Example 1
[
{ $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 2
[
{ $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 3
[
{ "x.a": { $gt: 85 }, "x.b": { $gt: 80 } }
]

For examples, see Array Update Operations with arrayFilters.

arrayFilters は、集計パイプラインが使用される更新では使用できません。

hint

ドキュメントまたは文字列

任意。query をサポートするために使用するインデックスを指定するドキュメントまたは文字列です。

このオプションには、インデックス仕様ドキュメントまたはインデックス名の文字列を指定できます。

存在しないインデックスを指定した場合、操作はエラーになります。

For an example, see Specify hint for findAndModify Operations.

comment

any

任意。このコマンドに添付するユーザー指定のコメント。設定すると、このコメントは以下の場所にこのコマンドの記録と合わせて表示されます。

コメントには、有効な BSON 型(string, integer, object, array など)を使用できます。

ドキュメント

任意。

変数のリストを含むドキュメントを指定します。これにより、変数をクエリテキストから分離することで、コマンドの読みやすさを向上させることができます。

ドキュメントの構文は次のとおりです。

{
<variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n>
}

変数は式によって返された値に設定され、その後は変更できません。

コマンド内の変数の値にアクセスするには、二重ドル記号の接頭辞($$)を $$<variable_name> 形式にした変数名とともに使用します。たとえば次のとおりです。$$targetTotal

結果のフィルタリングに変数を使用するには、$expr 演算子内の変数にアクセスする必要があります。

For a complete example using let and variables, see Use Variables in let.

バージョン 5.0 の新機能。

The findAndModify command returns a document with the following fields:

フィールド
タイプ
説明

value

ドキュメント

Contains the command's returned value. See value for details.

lastErrorObject

ドキュメント

Contains information about updated documents. See lastErrorObject for details.

ok

数値

コマンドの実行状態が入ります。成功した場合は 1、エラーが発生した場合は 0 になります。

lastErrorObject 埋め込みドキュメントには、次のフィールドが含まれています。

フィールド
タイプ
説明

updatedExisting

ブール値

update 操作が次の結果の場合、true が入ります。

  • 既存のドキュメントを更新しました。

  • ドキュメントは見つかりましたが、すでに目的の状態になっていたため、実際には更新は行われませんでした。

upserted

ドキュメント

upsert: trueを使用した update 操作によって新しいドキュメントが生成された場合、挿入されたドキュメントの ObjectId が入ります。

remove 操作では、クエリがドキュメントと一致する場合、value には削除されたドキュメントが入ります。クエリが削除するドキュメントと一致しない場合、value には null が入ります。

update 操作の場合、value 埋め込みドキュメントには次の内容が含まれます。

  • new パラメーターがセットされていないか、false の場合

    • クエリがドキュメントにマッチした場合、変更前のドキュメント。

    • それ以外の場合は、null

  • newtrueの場合

    • クエリが一致を返した場合、更新されたドキュメント。

    • upsert: trueでクエリに一致するドキュメントがない場合、挿入されたドキュメント。

    • それ以外の場合は、null

重複を防ぐためのユニークインデックスがない限り、アップサートによって重複したドキュメントが作成されることがあります。

Andy という名前のドキュメントが存在せず、複数のクライアントがほぼ同時に次のコマンドを発行する例を考えます。

db.runCommand(
{
findAndModify: "people",
query: { name: "Andy" },
update: { $inc: { score: 1 } },
upsert: true
}
)

If all findAndModify operations finish the query phase before any client successfully inserts data, and there is no unique index on the name field, each findAndModify operation may result in an insert, creating multiple documents with name: Andy.

A unique index on the name field ensures that only one document is created. With a unique index in place, the multiple findAndModify operations now exhibit the following behavior:

  • Exactly one findAndModify operation will successfully insert a new document.

  • Other findAndModify operations either update the newly-inserted document or fail due to a unique key collision.

    In order for other findAndModify operations to update the newly-inserted document, all of the following conditions must be met:

    • ターゲット コレクションに一意なインデックスがあるため、重複キー エラーが発生。

    • 更新操作が updateMany ではない、または multifalse

    • アップデートの一致条件は、次のいずれかです。

      • 単一の等価述語。例: { "fieldA" : "valueA" }

      • 等価述語の論理 AND。例: { "fieldA" : "valueA", "fieldB" : "valueB" }

    • 等価述語内のフィールドが、一意なインデックス キー パターン内のフィールドと一致。

    • 更新操作が、一意なインデックス キー パターン内のフィールドを変更しない。

次の表に示す upsert 操作の例では、キーの衝突が発生した場合に更新されるか失敗します。

ユニークインデックスキーのパターン
アップデート操作
結果
{ name : 1 }
db.people.updateOne(
{ name: "Andy" },
{ $inc: { score: 1 } },
{ upsert: true }
)

マッチしたドキュメントの score フィールドが 1 インクリメントされます。

{ name : 1 }
db.people.updateOne(
{ name: { $ne: "Joe" } },
{ $set: { name: "Andy" } },
{ upsert: true }
)

一意なインデックス キー パターン(name)のフィールドが変更されるため、操作は失敗します。

{ name : 1 }
db.people.updateOne(
{ name: "Andy", email: "andy@xyz.com" },
{ $set: { active: false } },
{ upsert: true }
)

等式述語フィールド(nameemail)がインデックス キー フィールド(name)と一致しないため、操作は失敗します。

To use findAndModify on a sharded collection:

  • 1つのシャードのみをターゲットにする場合は、query フィールドで部分的なシャードキーを使用できます。または

  • query フィールドの完全なシャードキーに等価条件を指定できます。

シャーディングされたコレクション内のドキュメントには、シャードキー フィールドがない場合があります。シャードキーがないドキュメントを対象とするには、null の等価一致を別のフィルター条件(_id フィールド上と同様に)と組み合わせて使用できます。例:

{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key

シャードキー フィールドが不変の _id フィールドでない限り、ドキュメントのシャードキー値を更新できます。

警告

シャーディングされたコレクション内のドキュメントには、シャード キー フィールドがないことがあります。ドキュメントのシャード キーの値を変更するときに、誤ってシャード キーを削除しないように注意してください。

To update the existing shard key value with findAndModify:

  • 必ず mongos 上で実行してください。操作をシャードで直接実行しないでください。

  • トランザクション内で、または 再試行可能な書き込みとして実行する必要があります

  • 完全なシャードキーに等価フィルターを含める必要があります

Documents in a sharded collection can be missing the shard key fields. To use findAndModify to set the document's missing shard key:

  • 必ず mongos 上で実行してください。操作をシャードで直接実行しないでください。

  • 新しいシャードキー値が null でない場合は、トランザクション内で実行するか、再試行可能な書き込みとして実行する必要があります

  • 完全なシャードキーに等価フィルターを含める必要があります

Tip

欠落しているキー値は NULL 等価一致の一部として返されるため、NULL 値のキーが更新されないように、必要に応じて追加のクエリ条件(_id フィールドなど)を追加します。

以下も参照してください。

The findAndModify command adds support for the bypassDocumentValidation option, which lets you bypass schema validation when inserting or updating documents in a collection with validation rules.

When updating a document, findAndModify and the updateOne() method operate differently:

  • If multiple documents match the update criteria, for findAndModify, you can specify a sort to provide some measure of control on which document to update.

    updateOne() は一致する最初のドキュメントを更新します。

  • By default, findAndModify returns an object that contains the pre-modified version of the document, as well as the status of the operation. To obtain the updated document, use the new option.

    updateOne() メソッドは、操作のステータスを含む WriteResult() オブジェクトを返します。

    更新されたドキュメントを返すには、find() メソッドを使用します。ただし、更新してからドキュメントを取得するまでの間に、他の更新によってドキュメントが変更される可能性があります。また、更新によって 1 つのドキュメントのみが変更されたが、複数のドキュメントが一致した場合は、更新されたドキュメントを識別するために追加のロジックを使用する必要があります。

When modifying a single document, both findAndModify and the updateOne() method atomically update the document. See Atomicity and Transactions for more details about interactions and order of operations of these methods.

findAndModify can be used inside distributed transactions.

重要

ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。

トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。

トランザクションがクロスシャード間書き込みトランザクション(write transaction)でない場合に、分散トランザクション内にコレクションとインデックスを作成できます。

findAndModify with upsert: true can be run on an existing collection or a non-existing collection. If run on a non-existing collection, the operation creates the collection.

トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。

書込み保証 (write concern)が満たされなかっために findAndModify操作が失敗した場合、操作はwriteConcernErrorドキュメントを返します。

次のコマンドは、people コレクション内の既存のドキュメントで、ドキュメントが query 条件に一致するものを更新します。

db.runCommand(
{
findAndModify: "people",
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
}
)

このコマンドは、次のアクションを実行します。

  1. query は、name フィールドの値が Tomstate フィールドの値が activerating フィールドの値が greater than 10 であるドキュメントを people コレクション内で検索します。

  2. sort は、クエリの結果を昇順に並べます。複数のドキュメントが query 条件に一致する場合、コマンドはソート順で最初のドキュメントを変更します。

  3. updatescore フィールドの値を 1 ずつ increments します。

  4. このコマンドは、次のフィールドを含むドキュメントを返します。

    • コマンドの詳細を含むlastErrorObjectフィールド( trueであるフィールドupdatedExistingを含む)と

    • この更新で選択された元の変更前のドキュメントを含む value フィールド:

      {
      "lastErrorObject" : {
      "connectionId" : 1,
      "updatedExisting" : true,
      "n" : 1,
      "syncMillis" : 0,
      "writtenTo" : null,
      "err" : null,
      "ok" : 1
      },
      value" : {
      "_id" : ObjectId("54f62d2885e4be1f982b9c9c"),
      "name" : "Tom",
      "state" : "active",
      "rating" : 100,
      "score" : 5
      },
      "ok" : 1
      }

更新されたドキュメントを value フィールドに返すには、コマンドに new:true オプションを追加します。

query 条件に一致するドキュメントがない場合、コマンドは value フィールドに null を含むドキュメントを返します。

{ "value" : null, "ok" : 1 }

mongosh and many drivers provide a findAndModify() helper method. Using the shell helper, this previous operation can take the following form:

db.people.findAndModify( {
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
} );

ただし、findAndModify() シェルヘルパー メソッドは変更されていないドキュメントのみを返します。または、newtrue の場合には、更新されたドキュメントを返します。

{
"_id" : ObjectId("54f62d2885e4be1f982b9c9c"),
"name" : "Tom",
"state" : "active",
"rating" : 100,
"score" : 5
}

次のコマンドはupsert: trueを使用して一致するドキュメントを更新するか、一致するドキュメントが存在しない場合は新しいドキュメントを挿入します。

db.runCommand(
{
findAndModify: "people",
query: { name: "Gus", state: "active", rating: 100 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true
}
)

コマンドが一致するドキュメントを見つけた場合、コマンドは更新を実行します。

一致するドキュメントが見つからない場合、upsert: trueupdate 操作によって挿入が行われ、次のフィールドを含むドキュメントが返されます。

  • コマンドの詳細を含む lastErrorObject フィールド(新しく挿入されたドキュメントの _id 値を含むフィールド upserted など)と

  • null を含む value フィールド。

{
"value" : null,
"lastErrorObject" : {
"updatedExisting" : false,
"n" : 1,
"upserted" : ObjectId("54f62c8bc85d4472eadea26f")
},
"ok" : 1
}

次のコマンドは、upsert: truenew: trueの両方を使用して一致するドキュメントを更新するか、新しいドキュメントを挿入し、value フィールドに新しいドキュメントまたは更新されたドキュメントを返します。

次の例では、people コレクション内のどのドキュメントも query 条件に一致しません。

db.runCommand(
{
findAndModify: "people",
query: { name: "Pascal", state: "active", rating: 25 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true,
new: true
}
)

このコマンドは、value フィールドに新しく挿入されたドキュメントを返します。

{
"lastErrorObject" : {
"connectionId" : 1,
"updatedExisting" : false,
"upserted" : ObjectId("54f62bbfc85d4472eadea26d"),
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
"value" : {
"_id" : ObjectId("54f62bbfc85d4472eadea26d"),
"name" : "Pascal",
"rating" : 25,
"state" : "active",
"score" : 1
},
"ok" : 1
}

次の例では、rating フィールドに sort 仕様を含めることで、state の値が active であり、一致するドキュメントの中で最も rating が低い 1 つのドキュメントを people コレクションから削除します。

db.runCommand(
{
findAndModify: "people",
query: { state: "active" },
sort: { rating: 1 },
remove: true
}
)

このコマンドは、次のように、削除されたドキュメントを返します。

{
"lastErrorObject" : {
"connectionId" : 1,
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
"value" : {
"_id" : ObjectId("54f62a6785e4be1f982b9c9b"),
"name" : "XYZ123",
"score" : 1,
"state" : "active",
"rating" : 3
},
"ok" : 1
}

照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。

コレクション myCollは、次のドキュメントを含みます。

{ _id: 1, category: "café", status: "A" }
{ _id: 2, category: "cafe", status: "a" }
{ _id: 3, category: "cafE", status: "a" }

次の操作には照合オプションが含まれます。

db.runCommand(
{
findAndModify: "myColl",
query: { category: "cafe", status: "a" },
sort: { category: 1 },
update: { $set: { status: "Updated" } },
collation: { locale: "fr", strength: 1 }
}
)

この操作を実行すると次のドキュメントが返されます。

{
"lastErrorObject" : {
"updatedExisting" : true,
"n" : 1
},
"value" : {
"_id" : 1,
"category" : "café",
"status" : "A"
},
"ok" : 1
}

注意

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 ] }
] )

grades 配列内の 100 以上の全要素を更新するには、位置演算子 $[<identifier>]arrayFilters オプションとともに使用します。

db.runCommand(
{
findAndModify: "students",
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.runCommand(
{
findAndModify: "students2",
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 }
]
}

findAndModify は、更新の集計パイプラインを受け入れることができます。このパイプラインには次のステージが含まれる可能性があります。

集計パイプラインを使用すると、現在のフィールド値に基づいて条件付きの更新を表現したり、あるフィールドを別のフィールドの値を使用して更新するなど、より表現内容の多い更新ステートメントが可能になります。

たとえば、次のドキュメントを含むコレクション 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.runCommand(
{
findAndModify: "students2",
query: { "_id" : 1 },
update: [ { $set: { "total" : { $sum: "$grades.grade" } } } ],
new: true
}
)

注意

パイプラインで使用される $set は、更新演算子 $set ではなく、集計ステージ $set を参照します

操作後、コレクションには次のドキュメントが含まれます。

{
"_id" : 1,
"grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" :85, "std" : 6 } ],
"total" : 250
}
{
"_id" : 2,
"grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85,"std" : 4 } ]
}

In mongosh, create a members collection with the following documents:

db.members.insertMany( [
{ "_id" : 1, "member" : "abc123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" },
{ "_id" : 3, "member" : "lmn123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 4, "member" : "pqr123", "status" : "D", "points" : 20, "misc1" : "Deactivated", "misc2" : null },
{ "_id" : 5, "member" : "ijk123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 6, "member" : "cde123", "status" : "A", "points" : 86, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
] )

コレクションに次のインデックスを作成します。

db.members.createIndex( { status: 1 } )
db.members.createIndex( { points: 1 } )

次の操作は、インデックス { status: 1 } を使用することを明示的に示しています。

db.runCommand({
findAndModify: "members",
query: { "points": { $lte: 20 }, "status": "P" },
remove: true,
hint: { status: 1 }
})

注意

存在しないインデックスを指定した場合、操作はエラーになります。

使用されたインデックスを確認するには、次の操作で explain を実行します。

db.runCommand(
{
explain: {
findAndModify: "members",
query: { "points": { $lte: 20 }, "status": "P" },
remove: true,
hint: { status: 1 }
},
verbosity: "queryPlanner"
}
)

バージョン 5.0 の新機能。

コマンド内の他の場所からアクセスできる変数を定義するには、 letオプションを使用します。

注意

変数を使用して結果をフィルタリングするには、$expr 演算子内の変数にアクセスする必要があります。

コレクション cakeFlavors を以下ように作成します。

db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )

次の例では、lettargetFlavor 変数を定義し、その変数を使用してケーキのフレーバーをチェリーからオレンジに変更します。

db.cakeFlavors.runCommand( {
findAndModify: db.cakeFlavors.getName(),
query: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } },
update: { flavor: "orange" },
let: { targetFlavor: "cherry" }
} )