MongoDB とドライバー
このページでは、 mongosh メソッドについて説明します。MongoDB ドライバーで同等のメソッドを確認するには、ご使用のプログラミング言語の対応するページを参照してください。
注意
MongoDB 8.0 における新しい一括書き込みコマンド
MongoDB 8.0 以降では、Mongo.bulkWrite() mongosh メソッドを使用して、複数のデータベースやコレクションに対する一括書き込みを実行できます。その他の一括書き込みメソッドやコマンドについては、「一括書き込み操作」を参照してください。
定義
db.collection.bulkWrite()1 つのコレクションに対して複数の書き込み操作を実行し、実行順序を制御します。
次の値を返します。 - 書込み保証付きで操作が実行された場合は
acknowledgedのブール値はtrueに、書込み保証が無効の場合はfalseになります。 - 各書き込み操作のカウント。
- 正常に挿入またはアップサートされた各ドキュメントの
_idを含む配列。
- 書込み保証付きで操作が実行された場合は
互換性
db.collection.bulkWrite() は、次の環境でホストされている配置で利用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
注意
このコマンドは、すべての MongoDB Atlas クラスターでサポートされています。すべてのコマンドに対する Atlas のサポートについては、「サポートされていないコマンド」を参照してください。
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
注意
Atlas UI では一括書込み操作を実行できません。複数のドキュメントを挿入するには、ドキュメントの配列を挿入する必要があります。詳細については、Atlas ドキュメントの「ドキュメントの作成、表示、アップデート、および削除」を参照してください。
構文
bulkWrite() メソッドの形式は次のとおりです。
db.collection.bulkWrite( [ <operation 1>, <operation 2>, ... ], { writeConcern : <document>, ordered : <boolean> } )
パラメーター
bulkWrite() メソッドは次のパラメータを取ります。
Parameter | タイプ | 説明 | ||
|---|---|---|---|---|
| 配列 |
有効な操作は次のとおりです。 | ||
| ドキュメント | 任意。書込み保証(write concern)を表現するドキュメント。デフォルトの書込み保証を使用する場合は省略します。 トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。 | ||
| ブール値 |
|
動作
bulkWrite() 書込み操作の配列を受け取り、それぞれを実行します。デフォルトでは、操作は順番に実行されます。書込み (write )操作の実行順序を制御するには、「 操作の実行 」を参照してください。
書込み操作
insertOne
コレクションに単一のドキュメントを挿入します。
db.collection.bulkWrite( [ { insertOne : { "document" : <document> } } ] )
updateOne と updateMany
updateOne は、コレクション内でフィルターに一致する単一のドキュメントをアップデートします。複数のドキュメントが一致する場合、updateOne は最初に一致したドキュメントのみをアップデートします。
db.collection.bulkWrite( [ { updateOne : { "filter": <document>, "update": <document or pipeline>, "upsert": <boolean>, "collation": <document>, "arrayFilters": [ <filterdocument1>, ... ], "hint": <document|string> } } ] )
updateMany は、コレクション内でフィルターに一致するすべてのドキュメントをアップデートします。
db.collection.bulkWrite( [ { updateMany : { "filter" : <document>, "update" : <document or pipeline>, "upsert" : <boolean>, "collation": <document>, "arrayFilters": [ <filterdocument1>, ... ], "hint": <document|string> } } ] )
フィールド | ノート |
|---|---|
| 更新の選択基準。 |
| |
| 任意。アップサートを実行するかどうかを示すブール値。 デフォルトでは、 |
| 任意。配列フィールドの更新操作でどの配列要素を変更するかを決定するフィルター ドキュメントの配列。 |
| 任意。操作に使用する照合を指定します。 |
| 任意。アップデート |
replaceOne
replaceOne フィルタにマッチするコレクション内の単一のドキュメントを置き換えます。複数のドキュメントが一致する場合、replaceOne は最初に一致したドキュメントのみを置換します。
db.collection.bulkWrite([ { replaceOne : { "filter" : <document>, "replacement" : <document>, "upsert" : <boolean>, "collation": <document>, "hint": <document|string> } } ] )
フィールド | ノート |
|---|---|
| 置換操作の選択基準。 |
| 置換ドキュメントです。このドキュメントに更新演算子を含めることはできません。 |
| 任意。アップサートを実行するかどうかを示すブール値。デフォルトでは、 |
| 任意。操作に使用する照合を指定します。 |
| 任意。アップデート |
deleteOne と deleteMany
deleteOne は、コレクション内でフィルターに一致する単一のドキュメントを削除します。複数のドキュメントが一致する場合、deleteOne は最初に一致したドキュメントのみを削除します。
db.collection.bulkWrite([ { deleteOne : { "filter" : <document>, "collation" : <document> // Available starting in 3.4 } } ] )
deleteMany は、コレクション内でフィルターに一致するすべてのドキュメントを削除します。
db.collection.bulkWrite([ { deleteMany: { "filter" : <document>, "collation" : <document> // Available starting in 3.4 } } ] )
フィールド | ノート |
|---|---|
| 削除操作の選択基準。 |
| 任意。操作に使用する照合を指定します。 |
_id フィールド
ドキュメントで _id フィールドが指定されていない場合は、 mongod で _id フィールドが追加され、ドキュメントの挿入またはアップサートの前にユニークな ObjectId() が割り当てられます。ほとんどのドライバーでは ObjectId が作成され、 _id フィールドが挿入されますが、ドライバーやアプリケーションでこの処理が行われない場合は、 mongod で_id の作成と入力が行われます。
ドキュメントに _id フィールドが含まれる場合に重複キー エラーを回避するには、_id 値がコレクション内で一意になるようにする必要があります。
更新操作または置換操作では、元のドキュメントと異なる _id 値を指定することはできません。
操作の実行
ordered パラメーターは、操作が連続して実行されるか、任意の順序で実行されるかを制御します。
ordered : true(デフォルトでは )の場合、操作は連続して実行されます。エラーが発生すると、後続の操作は実行されません。
ordered : false を使用すると、 操作は並列に実行される可能性があります。一部の操作が失敗した場合でも、エラーのないすべての操作が完了します。
各グループ内の操作の数は、データベースの maxWriteBatchSize の値を超えることはできません。maxWriteBatchSize のデフォルト値は 100,000 です。この値は hello.maxWriteBatchSize フィールドに表示されます。
この制限により、エラー メッセージの肥大化の問題が回避されます。この制限を超えるグループがある場合、クライアント ドライバーによって、操作数が制限値以下となる小さなグループに分割されます。たとえば、maxWriteBatchSize の値が 100,000 の場合、キューに 200,000 回の操作が含まれていると、ドライバによってそれぞれの操作回数が 100,000 回となるグループが 2 個作成されます。
注意
ドライバーによってグループが複数の小さなグループに分割されるのは、ハイレベル API を使用している場合のみに限られます。db.runCommand() を直接使用する場合(たとえばドライバーを書き込む場合)、制限を超えるバッチ書込みを実行しようとすると、MongoDB ではエラーがスローされます。
1 つのバッチのエラーレポートが大きくなりすぎた場合、MongoDB では残りのすべてのエラーメッセージを切り捨てて空の文字列にします。少なくとも 2 つのエラーメッセージがあり、合計サイズが 1MB を超える場合、これらは切り捨てられます。
サイズとグループ化の仕組みは内部的パフォーマンスの細部に該当し、今後のバージョンで変更される可能性があります。
シャーディングされたコレクションで ordered 操作リストを実行すると、通常、 unordered リストの実行よりも時間がかかります。これは、ordered リストでは毎回の操作で前の操作の完了を待機する必要があるためです。
上限付きコレクション
bulkWrite() Capped コレクションには制限があります。
updateOneアップデートによってドキュメントサイズが増加する場合には、 と により がスローされます。updateManyWriteErrorreplaceOneでは、置き換えドキュメントが元のドキュメントよりも大きい場合はWriteErrorがスローされます。deleteOneとdeleteManyは、上限付きコレクションに対してWriteErrorをスローします。
Error Handling
bulkWrite() は、エラー時にBulkWriteError の例外をスローします。 「 トランザクション内でのエラー処理 」を参照してください。
書込み保証( write concern ) エラーを除き、順序付き操作はエラーの発生後に停止します。一方、順序なし操作は、トランザクション内で実行されない限り、キューにある残りの書込み操作の処理を続行します。 「トランザクション内でのエラー処理 」を参照してください。
書込み保証エラーは writeConcernErrors フィールドに表示され、その他すべてのエラーは writeErrors フィールドに表示されます。エラーが発生した場合、挿入された_id 値の代わりに、成功した書き込み操作の数が表示されます。実行順序の決まった操作では、発生したエラーが 1 つだけ表示され、実行順序のない操作では 1 つの配列内のそれぞれのエラーが表示されます。
スキーマ検証エラー
コレクションでスキーマ検証が使用されており、 validationActionがerrorに設定されている場合、無効なドキュメントを挿入したり、無効な値を持つドキュメントを更新したりすると、エラーがスローされます。 operations配列内の無効な操作に先行する操作が実行され、 コレクションに書き込まれます。 orderedフィールドは、残りの操作が実行されるかどうかを決定します。
トランザクション
bulkWrite() は 分散トランザクション 内で使用できます。
重要
ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。
トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。
トランザクション内での挿入とアップサート
機能の互換性バージョン (FCV) が"4.4" 以上の場合、存在しないコレクションに対してトランザクションで upsert: true を使用した挿入操作またはアップデート操作を実行すると、コレクションが暗黙的に作成されます。
注意
クロスシャードの書き込みトランザクションでは新しいコレクションを作成できません。たとえば、あるシャードで既存コレクションに書き込み、別のシャードで暗示的にコレクションを作成する場合、MongoDB では同じトランザクションで両方の操作を実行できません。
書込み保証とトランザクション
トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。
トランザクション内のエラー処理
MongoDB4 .2 以降では、トランザクション内で db.collection.bulkWrite() 操作にエラーが発生した場合、メソッドは BulkWriteException をスローします (トランザクション外と同様)。
4.0 では、 bulkWrite 操作でトランザクション内のエラーが発生した場合、スローされたエラーは BulkWriteException としてはラップされません。
トランザクション内では、一括書き込みで最初のエラーが発生すると、順序付けがない場合であっても一括書き込み全体が失敗し、トランザクションが中止されます。
例
順序付き一括書込みの例
bulkWrite() の操作順序とエラー処理を理解することが重要です。デフォルトでは 、bulkWrite() は順序が付いたリストの操作を実行します。
操作は連続して実行されます。
操作にエラーがある場合、その操作および後続の操作は実行されません。
エラー操作が完了する前に一覧表示された操作。
bulkWrite() の例では、 pizzasコレクションを使用します。
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
次の db.collection.bulkWrite() の例では、pizzas コレクションに対して次の操作を実行します。
insertOneを使用して 2 つのドキュメントを追加します。updateOneを使用してドキュメントをアップデートします。deleteOneを使用してドキュメントを削除します。replaceOneを使用してドキュメントを置換します。
try { db.pizzas.bulkWrite( [ { insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } }, { insertOne: { document: { _id: 4, type: "sausage", size: "large", price: 10 } } }, { updateOne: { filter: { type: "cheese" }, update: { $set: { price: 8 } } } }, { deleteOne: { filter: { type: "pepperoni"} } }, { replaceOne: { filter: { type: "vegan" }, replacement: { type: "tofu", size: "small", price: 4 } } } ] ) } catch( error ) { print( error ) }
完了した操作の概要を含む出力例を示します。
{ acknowledged: true, insertedCount: 2, insertedIds: { '0': 3, '1': 4 }, matchedCount: 2, modifiedCount: 2, deletedCount: 1, upsertedCount: 0, upsertedIds: {} }
前の bulkWrite() の例を実行中前に、コレクションに _id が 4 のドキュメントがすでに含まれていた場合、2 番目の insertOne操作に対して次の重複キー例外が返されます。
writeErrors: [ WriteError { err: { index: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 4 }', op: { _id: 4, type: 'sausage', size: 'large', price: 10 } } } ], result: BulkWriteResult { result: { ok: 1, writeErrors: [ WriteError { err: { index: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 4 }', op: { _id: 4, type: 'sausage', size: 'large', price: 10 } } } ], writeConcernErrors: [], insertedIds: [ { index: 0, _id: 3 }, { index: 1, _id: 4 } ], nInserted: 1, nUpserted: 0, nMatched: 0, nModified: 0, nRemoved: 0, upserted: [] } }
bulkWrite() の例は順序付けられているため、最初の insertOne操作のみが完了します。
エラーのないすべての操作を完了するには、ordered を false に設定して bulkWrite() を実行します。の例については、次のセクションを参照してください。
順序付けなし一括書込みの例
順序付けられていない bulkWrite() を指定するには、ordered を false に設定します。
順序付けられていない bulkWrite() の操作リストでは次のようになります。
操作は並行して実行可能です(保証はされません)。詳細については順序付き操作と順序なし操作を参照してください。
エラーのある操作は完了しません。
エラーのないすべての操作が完了します。
pizzas コレクションの例を引き続き使用し、コレクションの削除と再作成を行います。
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
次の例を参照してください。
bulkWrite()は、pizzasコレクションに対して順序のない操作を実行します。2番目の
insertOne操作の_idは 1 番目のinsertOneと同じであるため、重複キー エラーが発生します。
try { db.pizzas.bulkWrite( [ { insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } }, { insertOne: { document: { _id: 3, type: "sausage", size: "large", price: 10 } } }, { updateOne: { filter: { type: "cheese" }, update: { $set: { price: 8 } } } }, { deleteOne: { filter: { type: "pepperoni"} } }, { replaceOne: { filter: { type: "vegan" }, replacement: { type: "tofu", size: "small", price: 4 } } } ], { ordered: false } ) } catch( error ) { print( error ) }
出力例には、重複キー エラーと完了した操作の概要が含まれています。
writeErrors: [ WriteError { err: { index: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 3 }', op: { _id: 3, type: 'sausage', size: 'large', price: 10 } } } ], result: BulkWriteResult { result: { ok: 1, writeErrors: [ WriteError { err: { index: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 3 }', op: { _id: 3, type: 'sausage', size: 'large', price: 10 } } } ], writeConcernErrors: [], insertedIds: [ { index: 0, _id: 3 }, { index: 1, _id: 3 } ], nInserted: 1, nUpserted: 0, nMatched: 2, nModified: 2, nRemoved: 1, upserted: [] } }
重複キー エラーのため、2 番目の insertOne操作は正常に実行されません。順序付けられていない bulkWrite() では、エラーのないすべての操作が完了します。
シャーディングされたクラスターでの書込み保証 (write concern) エラー
バージョン8.1.2で変更。
bulkWrite()mongosがシャーディングされたクラスター内のwriteConcernError で実行されると、他のエラーが 1 つ以上発生した場合でも、レスポンスには常に が報告されます。以前のリリースでは、他のエラーによって が書込み保証bulkWrite() (write concern)エラーを報告しないことがあります。
例、ドキュメントが検証に失敗して DocumentValidationFailed エラーが発生し、書込み保証 (write concern)エラーも発生した場合、DocumentValidationFailed エラーと writeConcernError の両方が応答の最上位フィールドに返されます。
書込み保証を使用した一括書込みの例
pizzas コレクションの例を引き続き使用し、コレクションの削除と再作成を行います。
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
次のbulkWrite() の例では、pizzas コレクションに対して操作を実行し、"majority" 100ミリ秒のタイムアウトで 書込み保証 (write concern)を設定します。
try { db.pizzas.bulkWrite( [ { updateMany: { filter: { size: "medium" }, update: { $inc: { price: 0.1 } } } }, { updateMany: { filter: { size: "small" }, update: { $inc: { price: -0.25 } } } }, { deleteMany: { filter: { size: "large" } } }, { insertOne: { document: { _id: 4, type: "sausage", size: "small", price: 12 } } } ], { writeConcern: { w: "majority", wtimeout: 100 } } ) } catch( error ) { print( error ) }
レプリカ セット ノードの大半が操作を確認するまでの時間が wtimeout を超えると、この例では書込み保証エラーと完了した操作の概要が返されます。
result: BulkWriteResult { result: { ok: 1, writeErrors: [], writeConcernErrors: [ WriteConcernError { err: { code: 64, codeName: 'WriteConcernTimeout', errmsg: 'waiting for replication timed out', errInfo: { wtimeout: true, writeConcern: [Object] } } } ], insertedIds: [ { index: 3, _id: 4 } ], nInserted: 0, nUpserted: 0, nMatched: 2, nModified: 2, nRemoved: 0, upserted: [], opTime: { ts: Timestamp({ t: 1660329086, i: 2 }), t: Long("1") } } }