update
定義
update
update
コマンドは、コレクション内のドキュメントを変更します。 単一のupdate
コマンドに複数のアップデート ステートメントを含めることができます。Tip
mongosh
では、このコマンドは 、updateOne()
、updateMany()
、replaceOne()
、findOneAndReplace()
、およびヘルパー メソッドfindOneAndUpdate()
を通じて実行することもできます。ヘルパー メソッドは
mongosh
ユーザーには便利ですが、データベースコマンドと同じレベルの情報は返されない可能性があります。 便宜上必要ない場合、または追加の戻りフィールドが必要な場合は、 データベースコマンドを使用します。
互換性
このコマンドは、次の環境でホストされている配置で使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
注意
このコマンドは、すべての MongoDB Atlas クラスターでサポートされています。すべてのコマンドに対する Atlas のサポートについては、 「サポートされていないコマンド」を参照してください。
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
バージョン 5.0 での変更。
update
コマンドの構文は次のとおりです。
db.runCommand( { update: <collection>, updates: [ { q: <query>, u: <document or pipeline>, c: <document>, // Added in MongoDB 5.0 upsert: <boolean>, multi: <boolean>, collation: <document>, arrayFilters: <array>, hint: <document|string> }, ... ], ordered: <boolean>, maxTimeMS: <integer>, writeConcern: { <write concern> }, bypassDocumentValidation: <boolean>, comment: <any>, let: <document> // Added in MongoDB 5.0 } )
コマンドフィールド
このコマンドは、次のフィールドを使用します。
フィールド | タイプ | 説明 | |||||
---|---|---|---|---|---|---|---|
update | string | ターゲット コレクションの名前。 | |||||
updates | 配列 | 名前付きコレクションに対して実行する 1 つ以上のアップデート ステートメントの配列。 更新 ステートメントの詳細については、「 更新 ステートメント 」を参照してください。 | |||||
ordered | ブール値 | オプション。 true の場合、アップデート ステートメントが失敗すると、残りのアップデート ステートメントを実行せずに戻ります。false の場合、アップデートが失敗すると、残りのアップデートス テートメントがあればそれを続行します。デフォルトは true です。 | |||||
maxTimeMS | non-negative integer | 任意。 時間制限をミリ秒単位で指定します。 MongoDB は、 | |||||
writeConcern | ドキュメント | 任意。 トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。 | |||||
bypassDocumentValidation | ブール値 | 任意。 操作中に update がドキュメント検証をバイパスできるようにします。 これにより、検証要件を満たさないドキュメントを更新できるようになります。 | |||||
comment | any | 任意。このコマンドに添付するユーザー指定のコメント。設定すると、このコメントは以下の場所にこのコマンドの記録と合わせて表示されます。
コメントには、有効な BSON 型(string, integer, object, array など)を使用できます。 | |||||
ドキュメント | 任意。 変数のリストを含むドキュメントを指定します。これにより、変数をクエリテキストから分離することで、コマンドの読みやすさを向上させることができます。 ドキュメントの構文は次のとおりです。
変数は式によって返された値に設定され、その後は変更できません。 コマンド内の変数の値にアクセスするには、二重ドル記号の接頭辞( 完全な例については、「 バージョン 5.0 で追加 |
アップデート ステートメント
updates
配列の各要素は、アップデート ステートメント ドキュメントです。各ドキュメントには、次のフィールドが含まれています。
フィールド | タイプ | 説明 | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ドキュメント | ||||||||||||||||||||
ドキュメントまたはパイプライン | 適用される修正。値は次のいずれかになります。
詳細については、「動作」を参照してください。 | |||||||||||||||||||
ドキュメント | オプション。u がパイプラインの場合にのみ 変数のリストを含むドキュメントを指定します。これにより、変数をクエリテキストから分離することで、コマンドの読みやすさを向上させることができます。 ドキュメントの構文は次のとおりです。
変数は式によって返された値に設定され、その後は変更できません。 コマンド内の変数の値にアクセスするには、二重ドル記号の接頭辞( 結果のフィルタリングに変数を使用するには、
バージョン 5.0 で追加 | |||||||||||||||||||
ブール値 | 任意。
複数のアップサートを回避するため、 デフォルトは | |||||||||||||||||||
multi | ブール値 | オプション。 複数のドキュメントをアップデートする場合、1 つのドキュメントがアップデートに失敗すると、それ以降のドキュメントはアップデートされません。この動作の詳細については、「Multiアップデートの失敗」を参照してください。 | ||||||||||||||||||
collation | ドキュメント | 任意。 操作に使用する照合を指定します。 照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。 照合オプションの構文は次のとおりです。
照合を指定する場合、 照合が指定されていなくても、コレクションにデフォルトの照合が設定されている場合( コレクションにも操作にも照合が指定されていない場合、MongoDB では以前のバージョンで使用されていた単純なバイナリ比較によって文字列が比較されます。 1 つの操作に複数の照合は指定できません。たとえば、フィールドごとに異なる照合を指定できません。また、ソートと検索を一度に実行する場合、検索とソートで別の照合を使用できません。 バージョン 3.4 で追加。 | ||||||||||||||||||
arrayFilters | 配列 | オプション。配列フィールドのアップデート操作でどの配列要素を変更するかを決定するフィルタードキュメントの配列。 アップデート ドキュメントでは、
アップデート ドキュメントには同じ識別子を複数回含めることができます。ただし、アップデート ドキュメント内の個別の識別子 (
ただし、次の例のように、単一のフィルター ドキュメント内の同じ識別子に複合条件を指定できます。
例については、「配列アップデート操作に バージョン 3.6 の新機能。 | ||||||||||||||||||
ドキュメントまたは文字列 | 任意。 クエリ述語 をサポートするために使用する インデックス を指定するドキュメントまたは string です。 このオプションには、インデックス仕様ドキュメントまたはインデックス名の文字列を指定できます。 存在しないインデックスを指定した場合、操作はエラーになります。 例については、「更新操作での |
戻り値
このコマンドは、操作のステータスを含むドキュメントを返します。例:
{ "ok" : 1, "nModified" : 0, "n" : 1, "upserted" : [ { "index" : 0, "_id" : ObjectId("52ccb2118908ccd753d65882") } ] }
出力フィールドの詳細については、「出力」を参照してください。
アクセス制御
authorization
を使用して実行されている配置では、ユーザーには次の特権を含むアクセス権が必要です。
組み込みロール readWrite
は必要な特権を提供します。
動作
更新演算子式ドキュメントを使用したアップデート
アップデートステートメントフィールド u は、 アップデート演算子式のみを含むドキュメントを受け入れることができます。例:
updates: [ { q: <query>, u: { $set: { status: "D" }, $inc: { quantity: 2 } }, ... }, ... ]
次に、 update
コマンドはドキュメント内の対応するフィールドのみを更新します。
置換ドキュメントによる更新
アップデート ステートメント フィールドuフィールドは置換ドキュメントを受け入れることができます。つまり、ドキュメントにはfield:value
式のみが含まれます。 例:
updates: [ { q: <query>, u: { status: "D", quantity: 4 }, ... }, ... ]
次に、 update
コマンドは一致するドキュメントをアップデート ドキュメントに置き換えます。 update
コマンドは一致するドキュメントを1 つだけ置き換えることができます。つまり、 multi
フィールドはtrue
にできません。 update
コマンドは_id
値を置き換えません。
Multi アップデートの失敗
multi
パラメータがtrue
に設定されたアップデートコマンドで 1 つのドキュメントのアップデートに失敗した場合、それ以上のドキュメントはそのコマンドの一部としてはアップデートされません。
たとえば、以下のドキュメントでmembers
コレクションを作成する場合、
db.members.insertMany( [ { "_id" : 1, "member" : "Taylor", "status" : "pending", "points" : 1}, { "_id" : 2, "member" : "Alexis", "status" : "enrolled", "points" : 59}, { "_id" : 3, "member" : "Elizabeth", "status" : "enrolled", "points" : 34} ] )
以下の操作では、 members
コレクションに、points
の値が と等しくならないというルールを持つ<a class=\" \" href=\" \">ドキュメント検証ツール60
を作成します。
db.runCommand( { collMod: "members", validator: { points: { $ne: 60 } } } )
このアップデート コマンドにより、すべてのドキュメントの points
フィールドの値を 1
増やします。
db.runCommand( { update: "members", updates: [ { q: {}, u: { $inc: { points: 1 } }, multi: true } ] } )
コマンドの実行後、コレクションには次のドキュメントが含まれます。
{ _id: 1, member: 'Taylor', status: 'A', points: 2 } { _id: 2, member: 'Alexis', status: 'D', points: 59 } { _id: 3, member: 'Elizabeth', status: 'C', points: 34 }
update コマンドでは 1 番目のドキュメントの points
の値がアップデートされましたが、2 番目のドキュメントはアップデートされませんでした。points
の値は 60
と等しくならないという検証ルールによるものです。書き込みエラー以降はドキュメントが更新されないため、3 番目のドキュメントは更新されませんでした。
注意
一致したドキュメントのサブセットが更新された場合、たとえば、更新によって一部のドキュメントがスキーマ検証に失敗する場合、update
コマンドによって返される nModified
の値は正確ではない可能性があります。
集計パイプラインによる更新
アップデート ステートメント フィールド u フィールドでは、集計パイプライン[ <stage1>, <stage2>, ... ]
を受け入れて、実行する変更を指定できます。パイプラインは、次のステージで構成できます。
$addFields
およびそのエイリアス$set
$replaceRoot
とそのエイリアス$replaceWith
。
集計パイプラインを使用すると、現在のフィールド値に基づいて条件付きのアップデートを表現したり、あるフィールドを他のフィールドの値を使用してアップデートするなど、より表現内容の多いアップデート ステートメントが可能になります。
以下に例を挙げます。
updates: [ { q: <query>, u: [ { $set: { status: "Modified", comments: [ "$misc1", "$misc2" ] } }, { $unset: [ "misc1", "misc2" ] } ], ... }, ... ]
例については、「集計パイプラインによる更新」を参照してください。
一意なインデックスを使用したアップサート
重複を防ぐためのユニークインデックスがない限り、アップサートによって重複したドキュメントが作成されることがあります。
Andy
という名前のドキュメントが存在せず、複数のクライアントがほぼ同時に次のコマンドを発行する例を考えます。
db.runCommand( { update: "people", updates: [ { q: { name: "Andy" }, u: { $inc: { score: 1 } }, multi: true, upsert: true } ] } )
いずれかのクライアントがデータを正常に挿入する前にすべての update
操作がクエリ フェーズを終了し、かつ name
フィールドにユニークインデックスがない場合、各 update
操作によって挿入が行われて、name: Andy
を含む複数のドキュメントが作成される可能性があります。
name
フィールドに一意なインデックスを設定すると、ドキュメントが 1 つだけ作成されるようになります。一意なインデックスが設定されると、複数の update
操作で次の動作が見られるようになります。
正確に 1 つの
update
操作で新しいドキュメントが正常に挿入されます。その他の
update
操作は、新しく挿入されたドキュメントを更新するか、一意なキーの競合が原因で失敗します。他の
update
操作で新しく挿入されたドキュメントを更新するには、次の条件がすべて満たされている必要があります。ターゲット コレクションに一意なインデックスがあるため、重複キー エラーが発生。
更新操作が
updateMany
ではない、またはmulti
がfalse
。アップデートの一致条件は、次のいずれかです。
単一の等価述語。例:
{ "fieldA" : "valueA" }
等価述語の論理 AND。例:
{ "fieldA" : "valueA", "fieldB" : "valueB" }
等価述語内のフィールドが、一意なインデックス キー パターン内のフィールドと一致。
更新操作が、一意なインデックス キー パターン内のフィールドを変更しない。
次の表に示す upsert
操作の例では、キーの衝突が発生した場合に更新されるか失敗します。
ユニークインデックスキーのパターン | アップデート操作 | 結果 | ||||||
---|---|---|---|---|---|---|---|---|
|
| マッチしたドキュメントの score フィールドが 1 インクリメントされます。 | ||||||
|
| 一意なインデックス キー パターン( name )のフィールドが変更されるため、操作は失敗します。 | ||||||
|
| 等式述語フィールド( name 、email )がインデックス キー フィールド(name )と一致しないため、操作は失敗します。 |
制限
updates
配列内の各アップデート要素について、クエリと更新サイズの合計(q
およびu
)は、最大 BSON ドキュメント サイズ以下である必要があります。
updates
配列内の更新ステートメントの総数は、最大バルクサイズ以下である必要があります。
ドキュメントの検証
update
コマンドはbypassDocumentValidation
オプションのサポートを追加します。これにより、検証ルールを使用してコレクションにドキュメントを挿入または更新するときにドキュメント検証をバイパスできます。
シャーディングされたコレクション
upsert
シャーディングされたコレクション
シャーディングされたコレクションでupdate
をmulti: false
と併用するには、
upsert: trueを指定しない場合、フィルターqは
_id
フィールドに等価一致を含めるか、単一のシャードをターゲットにする(シャードキーを含めるなど)必要があります。upsert: true を指定する場合、フィルターqにはシャードキーの等価一致が含まれている必要があります。
ただし、シャーディングされたコレクション内のドキュメントにはシャードキーのフィールドがない場合があります。シャードキーがないドキュメントを対象とするには、
null
を等価一致の を(_id
フィールド上と同じに)別のフィルター条件と組み合わせて使用できます。以下に例を挙げます。{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
ドキュメントの置換
ドキュメントを置き換えるとき、 update
は最初にクエリフィルターを使用して、1 つのシャードをターゲットにしようとします。 クエリフィルターで単一のシャードをターゲットにできない場合は、置き換えドキュメントをターゲットにしようとします。
シャードキーの変更
シャードキー フィールドが不変の _id
フィールドでない限り、ドキュメントのシャードキー値を更新できます。
既存のシャードキー値をupdate
で変更するには
必ず
mongos
上で使用します。シャードに直接操作を実行しないでください。トランザクション内で、または 再試行可能な書き込みとして実行する必要があります。
必ず
multi: false
を指定します。完全なシャードキーに等価のクエリフィルターを含める必要があります。
Tip
欠落しているキー値は NULL 等価一致の一部として返されるため、NULL 値のキーが更新されないように、必要に応じて追加のクエリ条件(_id
フィールドなど)を追加します。
「シャーディングされたコレクションの upsert
」も参照してください。
欠落しているシャードキー
シャーディングされたコレクション内のドキュメントには、シャードキー フィールドがない場合があります。update
を使用してドキュメントの欠落しているシャードキーを設定するには、mongos
で実行する必要があります。シャードに対して直接操作を実行しないでください。
さらに、次の要件も適用されます。
タスク | 要件 |
---|---|
設定するには null |
|
null 以外の値に設定するには、 |
|
Tip
欠落しているキー値は NULL 等価一致の一部として返されるため、NULL 値のキーが更新されないように、必要に応じて追加のクエリ条件(_id
フィールドなど)を追加します。
以下も参照してください。
トランザクション
update
は分散トランザクション内で使用できます。
重要
ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。
トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。
トランザクション内のアップサート
トランザクションがクロスシャード間書き込みトランザクション(write transaction)でない場合に、分散トランザクション内にコレクションとインデックスを作成できます。
update
と upsert: true
は、既存のコレクションまたは存在しないコレクションで実行できます。存在しないコレクションに対して実行すると、操作によってコレクションが作成されます。
書込み保証とトランザクション
トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。
例
1 つのドキュメントの特定のフィールドのアップデート
アップデート演算子を使用して、ドキュメントの指定されたフィールドのみを更新します。
たとえば、以下のドキュメントでmembers
コレクションを作成する場合、
db.members.insertMany([ { _id: 1, member: "abc123", status: "Pending", points: 0, misc1: "note to self: confirm status", misc2: "Need to activate" }, { _id: 2, member: "xyz123", status: "D", points: 59, misc1: "reminder: ping me at 100pts", misc2: "Some random comment" }, ])
次のコマンドは、 $set
および$inc
アップデート演算子を使用して、 member
が"abc123"
に等しいドキュメントのstatus
フィールドとpoints
フィールドを更新します。
db.runCommand( { update: "members", updates: [ { q: { member: "abc123" }, u: { $set: { status: "A" }, $inc: { points: 1 } } } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
<update>
ドキュメントではオプションの multi
フィールドが指定されていないため、q
一致条件に一致するドキュメントが複数ある場合でも、更新によって変更されるのは 1 つのドキュメントのみです。
返されたドキュメントは、コマンドによって複数のドキュメントが見つかり、更新されたことを示しています。このコマンドは、次を返します。
{ "n" : 1, "nModified" : 1, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
詳細については「出力」を参照してください。
コマンドの実行後、コレクションには次のドキュメントが含まれます。
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 1, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" } { "_id" : 2, "member" : "xyz123", "status" : "D", "points" : 59, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
1 つのドキュメントの特定のフィールドのアップデート
アップデート演算子を使用して、ドキュメントの指定されたフィールドのみを更新し、アップデート演算子に true
に設定された multi
フィールドを含めます。
たとえば、コレクション members
に次のドキュメントが含まれているとします。
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 1, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" } { "_id" : 2, "member" : "xyz123", "status" : "D", "points" : 59, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
次のコマンドは、 $set
および$inc
アップデート演算子を使用して、コレクション内の全ドキュメントの status
フィールドと points
フィールドをそれぞれ変更します。
db.runCommand( { update: "members", updates: [ { q: { }, u: { $set: { status: "A" }, $inc: { points: 1 } }, multi: true } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
アップデートにより、q
フィールドで指定されたクエリに一致するすべてのドキュメントが変更されます。これはつまり、コレクション内の全ドキュメントに一致する空のクエリです。
返されたドキュメントは、コマンドによって複数のドキュメントが見つかり、更新されたことを示しています。レプリカセットの場合、このコマンドは以下を返します。
{ "n" : 2, "nModified" : 2, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
詳細については「出力」を参照してください。
コマンドの実行後、コレクションには次のドキュメントが含まれます。
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 2, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" } { "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
集約パイプラインによるアップデート
update
コマンドは、更新に集計パイプラインを使用できます。 このパイプラインには次のステージが含まれる可能性があります。
$addFields
およびそのエイリアス$set
$replaceRoot
とそのエイリアス$replaceWith
。
集計パイプラインを使用すると、現在のフィールド値に基づいて条件付きのアップデートを表現したり、あるフィールドを他のフィールドの値を使用してアップデートするなど、より表現内容の多いアップデート ステートメントが可能になります。
例 1
次の例では、集計パイプラインを使用して、ドキュメント内の他のフィールドの値を使用してフィールドを変更します。
members
コレクションには次の文書が含まれます。
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 2, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" } { "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
misc1
フィールドと misc2
フィールドを分けるのではなく、これらを新しい comments
フィールドにまとめるとします。次のアップデート操作では、集計パイプラインを使用して新しい comments
フィールドを追加し、コレクション内のすべてのドキュメントの misc1
フィールドと misc2
フィールドを削除します。
まず、
status
フィールドを"Modified"
に設定し、他の 2 つのフィールドmisc1
およびmisc2
の現在の内容が含まれる新しいフィールドcomments
を追加します。次に、
misc1
とmisc2
のフィールドを除きます。
db.runCommand( { update: "members", updates: [ { q: { }, u: [ { $set: { status: "Modified", comments: [ "$misc1", "$misc2" ] } }, { $unset: [ "misc1", "misc2" ] } ], multi: true } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
返されたドキュメントは、コマンドによって複数のドキュメントが見つかり、更新されたことを示しています。このコマンドは、次を返します。
{ "n" : 2, "nModified" : 2, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
詳細については「出力」を参照してください。
コマンドの実行後、コレクションには次のドキュメントが含まれます。
{ "_id" : 1, "member" : "abc123", "status" : "Modified", "points" : 2, "comments" : [ "note to self: confirm status", "Need to activate" ] } { "_id" : 2, "member" : "xyz123", "status" : "Modified", "points" : 60, "comments" : [ "reminder: ping me at 100pts", "Some random comment" ] }
例 2
集計パイプラインを使用すると、現在のフィールド値に基づく条件付きアップデートを実行したり、アップデート時に別個のフィールド値の計算に現在のフィールド値を使用することができます。
db.students.insertMany( [ { "_id" : 1, "tests" : [ 95, 92, 90 ] }, { "_id" : 2, "tests" : [ 94, 88, 90 ] }, { "_id" : 3, "tests" : [ 70, 75, 82 ] } ] );
集計パイプラインを使用すると、計算されたグレード平均およびレターグレードでドキュメントを更新することができます。
db.runCommand( { update: "students", updates: [ { q: { }, u: [ { $set: { average : { $avg: "$tests" } } }, { $set: { grade: { $switch: { branches: [ { case: { $gte: [ "$average", 90 ] }, then: "A" }, { case: { $gte: [ "$average", 80 ] }, then: "B" }, { case: { $gte: [ "$average", 70 ] }, then: "C" }, { case: { $gte: [ "$average", 60 ] }, then: "D" } ], default: "F" } } } } ], multi: true } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
- 第 1 ステージ
$set
ステージでは、tests
フィールドの平均に基づいて新しいフィールドaverage
を計算します。集計演算子$avg
の詳細については、$avg
を参照してください。- 第 2 ステージ
$set
ステージでは、前のステージで計算されたaverage
フィールドに基づいて新しいフィールドgrade
が計算されます。集計演算子$switch
の詳細については、$switch
を参照してください。
返されたドキュメントは、コマンドによって複数のドキュメントが見つかり、更新されたことを示しています。このコマンドは、次を返します。
{ "n" : 3, "nModified" : 3, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
コマンドの実行後、コレクションには次のドキュメントが含まれます。
{ "_id" : 1, "tests" : [ 95, 92, 90 ], "average" : 92.33333333333333, "grade" : "A" } { "_id" : 2, "tests" : [ 94, 88, 90 ], "average" : 90.66666666666667, "grade" : "A" } { "_id" : 3, "tests" : [ 70, 75, 82 ], "average" : 75.66666666666667, "grade" : "C" }
一括アップデート
次の例では、 members
コレクションに対して複数のアップデート操作を実行します。
db.runCommand( { update: "members", updates: [ { q: { status: "P" }, u: { $set: { status: "D" } }, multi: true }, { q: { _id: 5 }, u: { _id: 5, name: "abc123", status: "A" }, upsert: true } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
返されたドキュメントは、コマンドが 10
ドキュメントを変更し、_id
値 5
のドキュメントを挿入したことを示しています。詳細については「出力」を参照してください。
{ "ok" : 1, "nModified" : 10, "n" : 11, "upserted" : [ { "index" : 1, "_id" : 5 } ] }
照合の指定
バージョン 3.4 で追加。
照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。
コレクション myColl
は、次のドキュメントを含みます。
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
次の操作には照合オプションが含まれます。
db.runCommand({ update: "myColl", updates: [ { q: { category: "cafe", status: "a" }, u: { $set: { status: "Updated" } }, collation: { locale: "fr", strength: 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( { update: "students", updates: [ { q: { grades: { $gte: 100 } }, u: { $set: { "grades.$[element]" : 100 } }, arrayFilters: [ { "element": { $gte: 100 } } ], multi: true} ] } )
操作後、コレクションには次のドキュメントが含まれます。
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 100 ] } { "_id" : 3, "grades" : [ 95, 100, 100 ] }
ドキュメントの配列の特定の要素を更新する
次のドキュメントを使用してコレクション 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 } ] } ] )
grades
配列のすべての要素のうち、グレードが 85
以上のもので mean
フィールドの値を変更するには、フィルタリングされた位置演算子 $[<identifier>]
を arrayFilters
とともに使用します。
db.runCommand({ update: "students2", updates: [ { q: { }, u: { $set: { "grades.$[elem].mean" : 100 } }, arrayFilters: [ { "elem.grade": { $gte: 85 } } ], multi: true } ] })
操作後、コレクションには次のドキュメントが含まれます。
{ "_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" : 100, "std" : 6 }, { "grade" : 87, "mean" : 100, "std" : 3 }, { "grade" : 85, "mean" : 100, "std" : 4 } ] }
更新操作に hint
を指定する
次のドキュメントを使用してサンプルmembers
コレクションを作成します。
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({ update: "members", updates: [ { q: { "points": { $lte: 20 }, "status": "P" }, u: { $set: { "misc1": "Need to activate" } }, hint: { status: 1 }, multi: true } ] })
update コマンドは次を返します。
{ "n" : 3, "nModified" : 3, "ok" : 1 }
使用されたインデックスを確認するには、次の操作で explain
を実行します。
db.runCommand( { explain: { update: "members", updates: [ { q: { "points": { $lte: 20 }, "status": "P" }, u: { $set: { "misc1": "Need to activate" } }, hint: { status: 1 }, multi: true } ] }, verbosity: "queryPlanner" } )
explain
はドキュメントを変更しません。
let
オプションまたは c
フィールドでの変数の使用
バージョン 5.0 で追加
変数はletオプションまたはcフィールドで定義し、 updates
配列でアクセスできます。
注意
変数を使用して結果をフィルタリングするには、$expr
演算子内の変数にアクセスする必要があります。
コレクション cakeFlavors
を以下ように作成します。
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
次の例では、let
で targetFlavor
変数と newFlavor
変数を定義し、その変数を使用してケーキのフレーバーをチェリーからオレンジに変更します。
db.runCommand( { update: db.cakeFlavors.getName(), updates: [ { q: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, u: [ { $set: { flavor: "$$newFlavor" } } ] } ], let : { targetFlavor: "cherry", newFlavor: "orange" } } )
次の例では、c
で targetFlavor
変数と newFlavor
変数を定義し、その変数を使用してケーキのフレーバーをチョコレートからバニラに変更します。
db.runCommand( { update: db.cakeFlavors.getName(), updates: [ { q: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, u: [ { $set: { flavor: "$$newFlavor" } } ], c: { targetFlavor: "chocolate", newFlavor: "vanilla" } } ] } )
出力
返されるドキュメントには、次のフィールドのサブセットが含まれます。
update.n
update
コマンドはドキュメントアップデートの配列を受け入れます。その一部はアップサートになる場合があります。アップデートの場合、n
はアップデート対象として選択されたドキュメントの数です。アップサートの場合、挿入されたドキュメントのn
は1
になります。サーバーではすべてのアップデートとアップサートのn
値を足し、合計がupdate.n
として返されます。アップデート操作によってドキュメントに変更が生じない場合(例:
$set
式は値を現在の値にアップデートし、n
はnModified
より大きくなる可能性があります。
update.nModified
更新されたドキュメントの数。 フィールドの値を現在の値に設定するなど、アップデート操作によってドキュメントに変更が生じない場合、
nModified
はn
より小さくなる可能性があります。注意
一致したドキュメントのサブセットが更新された場合、たとえば、更新によって一部のドキュメントがスキーマ検証に失敗する場合、
update
コマンドによって返されるnModified
の値は正確ではない可能性があります。
update.writeErrors
更新操作中に発生したエラーに関する情報を含むドキュメントの配列。
writeErrors
配列には、エラーが発生した更新ステートメントごとにエラー ドキュメントが含まれています。各エラー ドキュメントには以下のフィールドが含まれます。
update.writeConcernError
書込み保証に関連するエラーを説明するドキュメント。
update.writeConcernError.errInfo.writeConcern
対応する操作に使用される書込み保証 (write concern) オブジェクトです。書込み保証 (write concern) オブジェクト フィールドの詳細については、「書込み保証 (write concern) の仕様」を参照してください。
書込み保証 (write concern) オブジェクトには、書込み保証 (write concern) のソースを示す以下のフィールドも含むことができます。
update.writeConcernError.errInfo.writeConcern.provenance
書込み保証 (write concern) が発生した場所を示す文字列値です(書込み保証 (write concern)
provenance
と呼ばれます)。次の表は、このフィールドに指定できる値とその意味を示しています。出所説明clientSupplied
書き込み保証(write concern)がアプリケーションで指定されました。customDefault
書込み保証 (write concern) は、カスタム定義されたデフォルト値に基づきます。setDefaultRWConcern
を参照してください。getLastErrorDefaults
書込み保証 (write concern) は、レプリカセットのsettings.getLastErrorDefaults
のフィールドに基づきます。implicitDefault
他の書き込み保証(write concern)が一切指定されていない状態で、サーバーから発生した書き込み保証。
前述のアップデート固有の戻りフィールドに加えて、 db.runCommand()
には追加情報が含まれます。
レプリカ セットの場合、
optime
、electionId
、$clusterTime
、およびoperationTime
。シャーディングされたクラスターの場合、
operationTime
および$clusterTime
。
これらのフィールドの詳細については db.runCommand レスポンスを参照してください。
以下は、アップサートを実行したupdate
コマンドが成功した場合に返されるドキュメントの例です。
{ "ok" : 1, "nModified" : 0, "n" : 1, "upserted" : [ { "index" : 0, "_id" : ObjectId("52ccb2118908ccd753d65882") } ] }
以下は、3 つのアップデートステートメントを含む一括アップデートで返されるドキュメントの例です。1 つのアップデートステートメントは成功し、他の 2 つのアップデートステートメントではエラーが発生しました。
{ "ok" : 1, "nModified" : 1, "n" : 1, "writeErrors" : [ { "index" : 1, "code" : 16837, "errmsg" : "The _id field cannot be changed from {_id: 1.0} to {_id: 5.0}." }, { "index" : 2, "code" : 16837, "errmsg" : "The _id field cannot be changed from {_id: 2.0} to {_id: 6.0}." }, ] }