MongoDB とドライバー
このページでは、mongosh メソッドについて説明します。MongoDBドライバーで同等のメソッドを確認するには、 プログラミング言語の対応するページを参照してください。
定義
db.collection.bulkWrite()実行順序の制御を使用して複数の書き込み操作を実行します。
次の値を返します。 - ブール値は、 書込み保証(write concern)が有効化されて操作が実行された場合は
trueとして、無効化されていた場合はfalseとしてacknowledgedされます。 - 各書き込み操作のカウント。
- 正常に挿入またはアップサートされた各ドキュメントの
_idを含む配列。
- ブール値は、 書込み保証(write concern)が有効化されて操作が実行された場合は
互換性
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> } } ] )
db.collection.insertOne() を参照してください。
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> } } ] )
フィールド | ノート |
|---|---|
| 更新の選択基準。 |
| |
| 任意。アップサートを実行するかどうかを示すブール値。 デフォルトでは、 |
| 任意。配列フィールドの更新操作でどの配列要素を変更するかを決定するフィルター ドキュメントの配列。 |
| 任意。操作に使用する照合を指定します。 |
| 任意。アップデート |
詳細については、db.collection.updateOne() と db.collection.updateMany() を参照してください。
replaceOne
replaceOne フィルタにマッチするコレクション内の単一のドキュメントを置き換えます。複数のドキュメントが一致する場合、replaceOne は最初に一致したドキュメントのみを置換します。
db.collection.bulkWrite([ { replaceOne : { "filter" : <document>, "replacement" : <document>, "upsert" : <boolean>, "collation": <document>, "hint": <document|string> } } ] )
フィールド | ノート |
|---|---|
| 置換操作の選択基準。 |
| 置換ドキュメントです。このドキュメントに更新演算子を含めることはできません。 |
| 任意。アップサートを実行するかどうかを示すブール値。デフォルトでは、 |
| 任意。操作に使用する照合を指定します。 |
| 任意。アップデート |
詳細については db.collection.replaceOne() を参照してください。
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 } } ] )
フィールド | ノート |
|---|---|
| 削除操作の選択基準。 |
| 任意。操作に使用する照合を指定します。 |
詳細については、db.collection.deleteOne() と db.collection.deleteMany() を参照してください。
_id フィールド
ドキュメントで _id フィールドが指定されていない場合は、 mongod で _id フィールドが追加され、ドキュメントの挿入またはアップサートの前にユニークな ObjectId() が割り当てられます。ほとんどのドライバーでは ObjectId が作成され、 _id フィールドが挿入されますが、ドライバーやアプリケーションでこの処理が行われない場合は、 mongod で_id の作成と入力が行われます。
ドキュメントに _id フィールドが含まれる場合に重複キー エラーを回避するには、_id 値がコレクション内で一意になるようにする必要があります。
更新操作または置換操作では、元のドキュメントと異なる _id 値を指定することはできません。
操作の実行
ordered パラメーターでは、bulkWrite() が順番に操作を実行するか指定します。デフォルトでは、操作は順番に実行されます。
次のコードは、5 つの操作を含む bulkWrite() を表します。
db.collection.bulkWrite( [ { insertOne : <document> }, { updateOne : <document> }, { updateMany : <document> }, { replaceOne : <document> }, { deleteOne : <document> }, { deleteMany : <document> } ] )
デフォルトである ordered : true の状態では、最初の操作 insertOne から最後の操作 deleteMany まで、各操作が順番に実行されます。
ordered が false に設定されている場合、パフォーマンスを向上させるために mongod によって操作の順序が並べ替えられることがあります。アプリケーションは操作の実行順序に依存すべきではありません。
次のコードは、6 つの操作を含む順序付けられていない bulkWrite() を表します。
db.collection.bulkWrite( [ { insertOne : <document> }, { updateOne : <document> }, { updateMany : <document> }, { replaceOne : <document> }, { deleteOne : <document> }, { deleteMany : <document> } ], { ordered : false } )
ordered : false の場合、操作の結果が異なる場合があります。たとえば、 deleteOne または deleteMany では、 insertOne、 updateOne、 updateMany、 replaceOne の操作の前に実行されるか、後に実行されるかによって、削除されるドキュメントの数が増減する場合があります。
各グループ内の操作の数は、データベースのmaxWriteBatchSizeの値を超えることはできません。 MongoDB 3.6 以降、この値は100,000です。 この値はhello.maxWriteBatchSizeフィールドに表示されます。
この制限により、エラー メッセージの肥大化の問題が回避されます。この制限を超えるグループがある場合、クライアント ドライバーによって、操作数が制限値以下となる小さなグループに分割されます。たとえば、maxWriteBatchSize の値が 100,000 の場合、キューに 200,000 回の操作が含まれていると、ドライバによってそれぞれの操作回数が 100,000 回となるグループが 2 個作成されます。
注意
ドライバーによってグループが複数の小さなグループに分割されるのは、ハイレベル API を使用している場合のみに限られます。 db.runCommand()を直接使用する場合(例えばドライバーを書き込む場合)、制限を超えるバッチ書込みを実行しようとすると、MongoDB ではエラーがスローされます。
MongoDB 3.6 以降では、1 つのバッチのエラーレポートが大きくなりすぎると、MongoDB は残りのすべてのエラーメッセージを切り捨てて空の string にします。 現在のところ、 は、少なくとも 2 つのエラーメッセージがあり、合計サイズが1MBを超えると、開始されます。
サイズとグループ化の仕組みは内部的パフォーマンスの細部に該当し、今後のバージョンで変更される可能性があります。
シャーディングされたコレクションで ordered 操作リストを実行すると、通常、 unordered リストの実行よりも時間がかかります。これは、ordered リストでは毎回の操作で前の操作の完了を待機する必要があるためです。
上限付きコレクション
bulkWrite() 書き込み (write) 操作は、上限付きコレクションで使用する場合、制限があります。
updateOne update 条件によって変更されているドキュメントのサイズが増加する場合には、 updateMany により WriteError がスローされます。
replaceOne replacement ドキュメントのサイズが元のドキュメントよりも大きい場合は WriteError がスローされます。
deleteOne deleteMany では、上限付きコレクションで使用された場合に WriteError がスローされます。
時系列コレクション
bulkWrite() 書込み (write) 操作は、時系列コレクションで使用する場合、制限があります。時系列コレクションで使用できるのは insertOne のみです。他のすべての操作は WriteError を返します。
Error Handling
db.collection.bulkWrite() は、エラー時に BulkWriteError 例外をスローします。「トランザクション内のエラー処理」を参照してください。
書込み保証エラーを除き、順序付き操作はエラーの発生後に停止します。一方、順序なし操作は、トランザクション内で実行されない限り、キューにある残りの書込み操作の処理を続行します。 「トランザクション内でのエラー処理 」を参照してください。
書込み保証エラーは writeConcernErrors フィールドに表示され、その他すべてのエラーは writeErrors フィールドに表示されます。エラーが発生した場合、挿入された_id 値の代わりに、成功した書き込み操作の数が表示されます。実行順序の決まった操作では、発生したエラーが 1 つだけ表示され、実行順序のない操作では 1 つの配列内のそれぞれのエラーが表示されます。
スキーマ検証エラー
コレクションでスキーマ検証が使用されており、 validationActionがerrorに設定されている場合、無効なドキュメントを挿入したり、無効な値を持つドキュメントを更新したりすると、エラーがスローされます。 operations配列内の無効な操作に先行する操作が実行され、 コレクションに書き込まれます。 orderedフィールドは、残りの操作が実行されるかどうかを決定します。
トランザクション
db.collection.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 } ] )
次の 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()では、エラーのないすべての操作が完了します。
書込み保証を使用した一括書込みの例
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 コレクションに対して操作を実行し、100 ミリ秒のタイムアウトで"majority"書込み保証 (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: 'WriteConcernFailed', 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") } } }