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 のバージョン
構文
updateMany()メソッドの形式は次のとおりです。
db.collection.updateMany( <filter>, <update>, { upsert: <boolean>, writeConcern: <document>, collation: <document>, arrayFilters: [ <filterdocument1>, ... ], hint: <document|string>, let: <document>, maxTimeMS: <int>, bypassDocumentValidation: <boolean> } )
パラメーター
updateMany() メソッドは次のパラメータを取ります。
Parameter | タイプ | 説明 | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ドキュメント | ||||||||||||||||||||
ドキュメントまたはパイプライン | 適用される変更内容。次のいずれかになります。
置き換えドキュメントを使用して更新するには、 | |||||||||||||||||||
| ブール値 | Optional. When
複数のアップサートを回避するため、 デフォルトは | ||||||||||||||||||
| ドキュメント | 任意。書込み保証(write concern)を表現するドキュメント。デフォルトの書込み保証を使用する場合は省略します。 トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。 | ||||||||||||||||||
| ドキュメント | 任意。 任意。操作に使用する照合を指定します。 照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。 照合オプションの構文は次のとおりです。 照合を指定する場合、 照合が指定されていなくても、コレクションにデフォルトの照合が設定されている場合( コレクションにも操作にも照合が指定されていない場合、MongoDB では以前のバージョンで使用されていた単純なバイナリ比較によって文字列が比較されます。 1 つの操作に複数の照合は指定できません。たとえば、フィールドごとに異なる照合を指定できません。また、ソートと検索を一度に実行する場合、検索とソートで別の照合を使用できません。 | ||||||||||||||||||
| 配列 | 任意。配列フィールドの更新操作でどの配列要素を変更するかを決定するフィルター ドキュメントの配列。 アップデート ドキュメントでは、
アップデート ドキュメントには同じ識別子を複数回含めることができます。ただし、アップデート ドキュメント内の個別の識別子 ( ただし、次の例のように、単一のフィルター ドキュメント内の同じ識別子に複合条件を指定できます。 For examples, see Specify | ||||||||||||||||||
ドキュメントまたは文字列 | Optional. A document or string that specifies the index to use to support the query predicate. このオプションには、インデックス仕様ドキュメントまたはインデックス名の文字列を指定できます。 存在しないインデックスを指定した場合、操作はエラーになります。 For an example, see Specify | |||||||||||||||||||
ドキュメント | 任意。 変数のリストを含むドキュメントを指定します。これにより、変数をクエリテキストから分離することで、コマンドの読みやすさを向上させることができます。 ドキュメントの構文は次のとおりです。 変数は式によって返された値に設定され、その後は変更できません。 コマンド内の変数の値にアクセスするには、二重ドル記号の接頭辞( 結果のフィルタリングに変数を使用するには、
| |||||||||||||||||||
integer | 任意。タイムアウトするまでに更新操作を実行する時間制限をミリ秒単位で指定します。 | |||||||||||||||||||
ブール値 | オプション。 |
戻り値
このメソッドは、次の内容を含むドキュメントを返します。
操作が書き込み保証付きで実行された場合はブール値
acknowledged(true)、書き込み保証が無効になっている場合はfalseになりますmatchedCount一致したドキュメントの数を含みますmodifiedCount変更されたドキュメントの数を含みますupsertedId、アップサートされたドキュメントの_idが含まれるupsertedCountアップサートされた文書の数を含む
アクセス制御
authorizationを使用して実行されている配置では、ユーザーには次の特権を含むアクセス権が必要です。
update指定したコレクションに対するアクション。find指定したコレクションに対するアクション。insert操作の結果がアップサートになる場合、指定されたコレクションに対して実行されるアクション。
組み込みロール readWrite は必要な特権を提供します。
動作
updateMany() は、コレクション内で filter と一致するすべてのドキュメントを検索し、update パラメータで指定された変更を適用します。
updateMany() は、各ドキュメントを個別に変更します。 各ドキュメントの書込みはアトミック操作ですが、 updateMany()全体はアトミックではありません。ユースユースケースで複数のドキュメントへの書込みのアトミック性が必要な場合は、 トランザクション を使用します。
1 つのドキュメントの更新が失敗した場合、失敗する前に書き込まれたすべてのドキュメントの更新は保持されますが、残りの一致するドキュメントは更新されません。この動作の詳細については、「 Multi更新の失敗 」を参照してください。
Tip
Sharded Collections for more information about updateMany() behavior in sharded collections.
制限
アップサート
upsert: true で、filter に一致するドキュメントがない場合、db.collection.updateMany() では filter と update パラメーターに基づき新しいドキュメントが作成されます。
If you specify upsert: true on a sharded collection, you must include the full shard key in the filter. For information about db.collection.updateMany() behavior in sharded collections, see Sharded Collections.
「アップサートによる複数のドキュメントの更新」を参照してください。
更新演算子式ドキュメントを使用したアップデート
変更仕様の場合、db.collection.updateMany() メソッドでは更新演算子式のみを含むドキュメントを受け入れることができます。
以下に例を挙げます。
db.collection.updateMany( <query>, { $set: { status: "D" }, $inc: { quantity: 2 } }, ... )
集計パイプラインによる更新
db.collection.updateMany() メソッドでは、実行する変更を指定する 集計パイプライン [ <stage1>, <stage2>, ... ] を受け入れることができます。パイプラインは次のステージで構成できます。
$addFieldsおよびそのエイリアス$set$replaceRootおよびそのエイリアス$replaceWith
集計パイプラインを使用すると、現在のフィールド値に基づいて条件付きのアップデートを表現したり、あるフィールドを他のフィールドの値を使用してアップデートするなど、より表現内容の多いアップデート ステートメントが可能になります。
以下に例を挙げます。
db.collection.updateMany( <query>, [ { $set: { status: "Modified", comments: [ "$misc1", "$misc2" ] } }, { $unset: [ "misc1", "misc2" ] } ] ... )
注意
このパイプラインでは、$set と $unset は集計ステージで、更新演算子とは対照的です。集計ステージ$setと$unsetでは、ドキュメントに新しいフィールドが追加され、既存のフィールド値は変更されません。
更新演算子の詳細については、 $setと$unsetを参照してください。
For examples, see Update with Aggregation Pipeline.
上限付きコレクション
更新操作によりドキュメントのサイズが変更された場合、操作は失敗します。
時系列コレクション
updateMany() メソッドは、MongoDB 5.1 以降の時系列コレクションで使用できます。
更新コマンドは、次の要件を満たしている必要があります。
照合できるのは、
metaFieldフィールドの値のみです。変更できるのは、
metaFieldフィールドの値のみです。更新ドキュメントには、更新演算子式しか含めることができません。
Your update command must not limit the number of documents to be updated. Set
multi: trueor use theupdateMany()method.更新コマンドでは upsert: true を設定しないでください。
シャーディングされたコレクション
updateMany() は、シャーディングされたコレクションで使用すると、次の動作を示します。
updateMany()upsert: trueを含む 操作には、filterに完全なシャードキーを含める必要があります。updateMany()範囲移行 またはシャードキー値の更新 中に を実行しようとすると、シナリオによっては操作によってドキュメントが失われる可能性があります。すべてのドキュメントが更新されるようにするには、 冪等更新 を使用し、それ以上の更新が適用されなくなるまでコマンドを再実行します。updateMany()を使用した冪等更新の詳細については、「 冪等更新 」を参照してください。
updateMany()がトランザクションの外で実行されると、複数のシャードを対象とする操作は、クラスター内のすべてのシャードに適用されます。updateMany()がトランザクション内で実行される場合、複数のシャードを対象とする操作は、関連するシャードのみを対象とします。
説明可能性
updateMany() db.collection.explain()は と互換性がありません。
トランザクション
db.collection.updateMany() は分散トランザクション内で使用できます。
重要
ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。
トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。
トランザクション内のアップサート
トランザクションがクロスシャード間書き込みトランザクション(write transaction)でない場合に、分散トランザクション内にコレクションとインデックスを作成できます。
db.collection.updateMany() upsert: true は、既存のコレクションまたは存在しないコレクションで実行できます。存在しないコレクションで実行すると、操作によってコレクションが作成されます。
書込み保証とトランザクション
トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。
Oplog エントリ
updateMany() は、正常にアップデートされた各ドキュメントのoplog (操作ログ)にエントリを追加します。ドキュメントが更新されていない場合、updateMany() はoplogにエントリを追加しません。
例
このページの例では、sample_mflix データセット のデータを使用しています。自己管理型 MongoDB 配置にこのデータセットをロードする方法の詳細については、「サンプル データセットのロード」を参照してください。サンプル データベースに何らかの変更を加えた場合は、今ページの例を実行するには、データベースを削除して再作成する必要がある可能性があります。
Idempotent Updates
sample_mflix.moviesコレクションには IMDB 評価の映画が含まれています。この冪等更新では、次の操作が実行されます。
は、 IMDB 評価が 3.0 未満のすべての映画に一致します
これらの評価は 0.5 ずつ増加します
ratingBoostedフィールドをtrueに設定する
db.movies.updateMany( { "imdb.rating": { $lt: 3, $type: "number" }, ratingBoosted: { $ne: true } }, { $inc: { "imdb.rating": 0.5 }, $set: { ratingBoosted: true } } )
updateMany() は、一致する映画ドキュメントを個別に変更します。個々のドキュメントの更新はアトミック操作ですが、updateMany()操作全体はアトミックではありません。
操作が失敗して一致するすべてのドキュメントのアップデートに失敗した場合は、指定されたフィルターに一致するドキュメントがなくなるまで、冪等コマンドを安全に再実行できます。 この場合、コマンドが冪等であるため、再試行回数に関係なく、各ドキュメントの imdb.ratingフィールドは 1 回だけ更新されます。
複数のドキュメントの更新
sample_mflix.moviesコレクションには、num_mflix_commentsフィールドを持つ映画が含まれています。
次の操作では、100 を超えるコメントがあるすべての映画を検索し、それらの映画に popular フラグを追加します。
db.movies.updateMany( { num_mflix_comments: { $gt: 100 } }, { $set: { "popular" : true } } )
集約パイプラインによるアップデート
db.collection.updateMany() can use an aggregation pipeline to express a more complex update, such as a conditional update based on current field values. For the supported pipeline stages, see Update with an Aggregation Pipeline.
例 1: 既存のフィールドを使用した集計パイプラインによる更新
次の例では、集計パイプラインを使用して、ドキュメント内の他のフィールドの値を使用してフィールドを変更します。
このパイプライン:
IMDB と ユーザーの評価を新しい
combinedRatings配列フィールドに結合しますratingsUpdatedフィールドを設定する一致するすべてのドキュメントの元の
imdb.ratingフィールドとtomatoes.viewer.ratingフィールドを削除
db.movies.updateMany( { year: { $gte: 2010, $lte: 2019 } }, [ { $set: { combinedRatings: [ "$imdb.rating", "$tomatoes.viewer.rating" ], ratingsUpdated: "$$NOW" } }, { $unset: [ "imdb.rating", "tomatoes.viewer.rating" ] } ] )
注意
このパイプラインでは、$set と $unset は集計ステージで、更新演算子とは対照的です。集計ステージ$setと$unsetでは、ドキュメントに新しいフィールドが追加され、既存のフィールド値は変更されません。
更新演算子の詳細については、 $setと$unsetを参照してください。
- 第 1 ステージ
$set段階:新しい配列フィールド
combinedRatingsを作成します。その要素としてはimdb.ratingフィールドとtomatoes.viewer.ratingフィールドの現在の内容を含めます。フィールド
ratingsUpdatedを集計変数NOWの値に設定します。
- 第 2 ステージ
$unsetステージでは、imdb.ratingフィールドとtomatoes.viewer.ratingフィールドが削除されます。
コマンドの後、2010 から一致する映画には、評価値とタイムスタンプの両方を含む combinedRatings 配列が含まれます。
例 2: 既存のフィールドの条件を使用した集計パイプラインによる更新
集計パイプラインを使用すると、計算された合計評価スコア( IMDB と ユーザーの平均評価)で 2010 の映画を更新し、そのスコアに基づいてレターグレードを割り当てることができます。
db.movies.updateMany( { year: { $gte: 2010, $lte: 2019 }, "imdb.rating": { $exists: true }, "tomatoes.viewer.rating": { $exists: true } }, [ { $set: { combinedScore: { $trunc: [ { $avg: [ "$imdb.rating", "$tomatoes.viewer.rating" ] }, 1 ] }, scoreUpdated: "$$NOW" } }, { $set: { ratingGrade: { $switch: { branches: [ { case: { $gte: [ "$combinedScore", 8 ] }, then: "A" }, { case: { $gte: [ "$combinedScore", 6 ] }, then: "B" }, { case: { $gte: [ "$combinedScore", 4 ] }, then: "C" }, { case: { $gte: [ "$combinedScore", 2 ] }, then: "D" } ], default: "F" } } } } ] )
注意
このパイプラインでは、$set と $unset は集計ステージで、更新演算子とは対照的です。集計ステージ$setと$unsetでは、ドキュメントに新しいフィールドが追加され、既存のフィールド値は変更されません。
更新演算子の詳細については、 $setと$unsetを参照してください。
- 第 1 ステージ
$set段階:フィールド
scoreUpdatedを集計変数NOWの値に設定します。
- 第 2 ステージ
$setステージでは、前のステージで計算されたcombinedScoreフィールドに基づいて新しいフィールドratingGradeが計算されます。集計演算子$switchの詳細については、$switchを参照してください。
コマンドの後、一致する映画には スコアとレター グレードが合計されます。
Tip
アップサートによる複数のドキュメントの更新
次の操作では、2020 後にリリースされ、クリストファー ノードが管理したすべての映画を更新します。
db.movies.updateMany( { year: { $gt: 2020 }, directors: "Christopher Nolan" }, { $set: { "upcomingRelease": true } }, { upsert: true } )
この例では、フィルターに一致するドキュメントがなく、upsert が true であるため、updateMany は生成された _id と filter からの等価条件、および update 修飾子を持つ新しいドキュメントを挿入します。
書き込み保証による更新
3つのノードから成るレプリカセットにおいて、次の操作は w の majority と wtimeout の 100 を指定します。
db.movies.updateMany( { title: "The Godfather" }, { $inc: { num_mflix_comments: 10 }, $set: { trending: true } }, { w: "majority", wtimeout: 100 } )
確認応答に wtimeout の制限を超える時間がかかると、 MongoDB は例外をスローします。
次の表は、errInfo.writeConcern.provenanceの値について説明したものです。
出所 | 説明 |
|---|---|
| 書き込み保証(write concern)がアプリケーションで指定されました。 |
| 書込み保証 (write concern) は、カスタム定義されたデフォルト値に基づきます。 |
| 書込み保証 (write concern) は、レプリカセットの |
| 他の書き込み保証(write concern)が一切指定されていない状態で、サーバーから発生した書き込み保証。 |
照合の指定
照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。
次の操作では、大文字と小文字を区別しない照合を使用して、小文字と大文字の任意の組み合わせを持つ、"drama" というジャンルの映画を照合します。
db.movies.updateMany( { genres: "drama" }, { $set: { genreNormalized: true } }, { collation: { locale: "en", strength: 1 } } )
配列更新操作での arrayFilters の指定
配列フィールドを更新するときに、どの配列要素を更新するかを決定するためのarrayFiltersを指定できます。
arrayFilters 条件に一致する要素を更新する
さまざまな評価スコアを組み合わせて、ratings 配列を一部の映画に追加します。
db.movies.updateMany( { "imdb.rating": { $exists: true }, "tomatoes.viewer.rating": { $exists: true }, "tomatoes.critic.rating": { $exists: true }, year: { $gte: 2010, $lte: 2015 } }, [ { $set: { ratings: [ { $multiply: ["$imdb.rating", 10] }, { $multiply: ["$tomatoes.viewer.rating", 10] }, { $multiply: ["$tomatoes.critic.rating", 10] } ] } } ] )
ratings 配列内の 100 以上の評価をすべて更新するには、フィルタリングされた位置演算子 $[<identifier>] を arrayFilters オプションとともに使用します。
db.movies.updateMany( { ratings: { $gte: 100 } }, { $set: { "ratings.$[element]" : 100 } }, { arrayFilters: [ { "element": { $gte: 100 } } ] } )
操作後、ratings 配列内の 100 以上のすべての評価値が 100 に設定されます。
ドキュメントの配列の特定の要素を更新する
個々の評価ソースを持つ映画に ratingDetails 配列を追加します。
db.movies.updateMany( { "imdb.rating": { $exists: true }, "tomatoes.viewer.rating": { $exists: true }, year: { $gte: 2010, $lte: 2012 } }, [ { $set: { ratingDetails: [ { source: "imdb", score: "$imdb.rating", weight: 10 }, { source: "tomatoes_viewer", score: "$tomatoes.viewer.rating", weight: 8 }, { source: "tomatoes_critic", score: "$tomatoes.critic.rating", weight: 7 } ] } } ] )
スコアが 8 以上である ratingDetails 配列のすべての要素に対して、weightフィールドの値を 10 に変更するには、フィルタリングされた位置演算子 $[<identifier>] と arrayFilters を使用します。
db.movies.updateMany( { ratingDetails: { $exists: true } }, { $set: { "ratingDetails.$[elem].weight" : 10 } }, { arrayFilters: [ { "elem.score": { $gte: 8 } } ] } )
操作後、スコアが 8 以下のすべての評価ソースは、重みを 10 に設定します。
更新操作に hint を指定する
次のインデックスをコレクションで作成します。
db.movies.createIndex( { rated: 1 } )
次の更新操作は、インデックス{ rated: 1 }を使用することを明示的に示しています。
注意
存在しないインデックスを指定した場合、操作はエラーになります。
db.movies.updateMany( { "num_mflix_comments": { $lte: 5 }, "rated": "G" }, { $set: { "familyFriendly": true } }, { hint: { rated: 1 } } )
ヒントで指定したインデックスが使用されているかどうかを確認するには、$indexStats パイプラインを実行します。
db.movies.aggregate( [ { $indexStats: { } }, { $sort: { name: 1 } }, { $match: {key: { rated: 1 } } } ] )
シャーディングされたクラスターでの書込み保証 (write concern) エラー
バージョン8.1.2で変更。
db.collection.updateMany() がシャーディングされたクラスター内の mongos で実行されると、他のエラーが 1 つ以上発生した場合でも、レスポンスには常に writeConcernError が報告されます。以前のリリースでは、他のエラーによって db.collection.updateMany() が書込み保証 (write concern)エラーを報告しないことがあります。
例、ドキュメントが検証に失敗して DocumentValidationFailed エラーが発生し、書込み保証 (write concern)エラーも発生した場合、DocumentValidationFailed エラーと writeConcernError の両方が応答の最上位フィールドに返されます。
ユーザーロールとドキュメントの更新
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 としてログインし、更新を実行します。
前の例では、$setIntersection を使用して、"Provider" s文字列と $$USER_ROLES.role のユーザー ロールの共通部分が空ではないドキュメントを返します。Michelle はProvider のロールを持つので、更新が実行されます。
次に、Provider ロールを持たない James としてログインし、同じ更新の実行を試みます。
前の例では、ドキュメントは更新されません。