db.collection.insertMany()
MongoDB とドライバー
このページでは、 mongosh
メソッドについて説明します。MongoDB ドライバーで同等のメソッドを確認するには、ご使用のプログラミング言語の対応するページを参照してください。
定義
db.collection.insertMany()
コレクションに複数のドキュメントを挿入します。
次の値を返します。 次の要素を含むドキュメント:
ブール値は、操作が
acknowledged
書込み保証( 書込み保証true
(write concern)false
)付きで実行された場合は に設定され、書込み保証 (write concern)が無効になっている場合は に設定されます。正常に挿入された各ドキュメントの
_id
値を含むinsertedIds
配列
互換性
次の環境でホストされる配置には db.collection.insertMany()
を使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
insertMany()
メソッドの構文は次のとおりです。
db.collection.insertMany( [ <document 1> , <document 2>, ... ], { writeConcern: <document>, ordered: <boolean> } )
Parameter | タイプ | 説明 |
---|---|---|
document | ドキュメント | コレクションに挿入するドキュメントの配列。 |
writeConcern | ドキュメント | 任意。書込み保証(write concern)を表現するドキュメント。デフォルトの書込み保証を使用する場合は省略します。 トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。 |
ordered | ブール値 | 任意。 mongod インスタンスが順序付き挿入を実行するか、順序なし挿入を実行するかを指定するブール値。デフォルト値は true です。 |
動作
ドキュメントの配列が指定された場合、 insertMany()
は配列内の各ドキュメントを コレクションに挿入します。
操作の実行
デフォルトでは、ドキュメントは提供された順序で挿入されます。
ordered
がtrue
に設定され、挿入に失敗した場合、サーバーはレコードの挿入を続行しません。
ordered
が false
に設定されている場合に挿入に失敗しても、サーバーはレコードの挿入を続行します。パフォーマンスを向上させるために、ドキュメントは mongod
によって並べ替えられる場合があります。使用する insertMany()
が順序付けられていない場合、アプリケーションは挿入順序に依存しません。
各グループ内の操作の数は、データベースの 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 リストでは毎回の操作で前の操作の完了を待機する必要があるためです。
コレクションの作成
コレクションが存在しない場合、 insertMany()
は書き込みが成功したときにコレクションを作成します。
_id
フィールド
ドキュメントに _id フィールドが指定されていない場合、mongod
は _id
フィールドを追加して、そのドキュメントにユニークな ObjectId()
を割り当てます。ほとんどのドライバーでは ObjectId が作成され、 _id
フィールドが挿入されますが、ドライバーやアプリケーションでこの処理が行われない場合は、 mongod
で_id
の作成と入力が行われます。
ドキュメントに _id
フィールドが含まれる場合に重複キー エラーを回避するには、_id
値がコレクション内で一意になるようにする必要があります。
説明可能性
Error Handling
挿入は BulkWriteError
の例外をスローします。
書込み保証(write concern)エラーを除き、順序付き操作はエラーの発生後に停止します。一方、順序なし操作はキューにある残りの書込み操作の処理を続行します。
書込み保証(write concern)エラーは writeConcernErrors
フィールドに表示され、その他すべてのエラーは writeErrors
フィールドに表示されます。エラーが発生した場合、挿入された _id のリストではなく、正常に実行された書込み操作の数が表示されます。順序付き操作では、発生したエラーが 1 つのみ表示され、順序なし操作では 1 つの配列内のそれぞれのエラーが表示されます。
スキーマ検証エラー
コレクションでスキーマ検証が使用されており、 validationAction
がerror
に設定されている場合、 db.collection.insertMany()
を使用して無効なドキュメントを挿入すると、 writeError
がスローされます。 documents
配列内の無効なドキュメントに先行するドキュメントは、 コレクションに書き込まれます。 残りの有効なドキュメントが挿入されるかどうかは、 ordered
フィールドの値によって決まります。
トランザクション
db.collection.insertMany()
は分散トランザクション内で使用できます。
重要
ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。
トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。
トランザクションでのコレクション作成
トランザクションがクロスシャード間書込みトランザクション(write transaction)でない場合に、分散トランザクション内にコレクションとインデックスを作成できます。
トランザクションにないコレクションに挿入を指定すると、MongoDB は暗黙的にコレクションを作成します。
書込み保証とトランザクション
トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。
無作為データのパフォーマンスに関する考慮事項
インデックス フィールドで大量の無作為データ(例: ハッシュされたインデックス)の挿入操作が実行される場合、挿入パフォーマンスが低下することがあります。無作為データを一括挿入すると、無作為のインデックスエントリが作成され、インデックスのサイズが増大します。無作為な挿入ごとに別のインデックスエントリへのアクセスが必要なサイズにインデックスが達した場合、挿入により WiredTiger キャッシュがエビクションおよび置き換えられる率が上昇します。こうした場合、インデックスは完全にキャッシュされなくなり、ディスク上で更新されるため、パフォーマンスが低下します。
インデックス フィールドでの無作為データの一括挿入動作を向上させるには、次のいずれかを実行します。
インデックスを削除し、無作為データを挿入した後に再度作成します。
インデックスのない空のコレクションにデータを挿入します。
一括挿入後にインデックスを作成すると、メモリ内のデータがソートされ、すべてのインデックスに対して順序付き挿入が実行されます。
Oplog エントリ
db.collection.insertMany()
操作によって 1 つ以上のドキュメントが正常に挿入されると、その操作によって挿入された各ドキュメント用のエントリが oplog(操作ログ)に追加されます。操作が失敗した場合、その操作によって oplog にエントリが追加されることはありません。
例
以下の例では、products
コレクションにドキュメントを挿入しています。
フィールドを指定せずに複数のドキュメントを挿入<a class=\" \" href=\" \" title=\" \"><svg_id
xmlns=\" \" width=\" \" height=\" \" fill=\" \" viewbox=\" \" class=\" \" role=\" \" aria-label=\" \"><path fill=\" \" d=\" \"> <path fill=\" \" d=\" \">
次の例では、db.collection.insertMany()
を使用して、_id
フィールドを含まないドキュメントを挿入しています。
try { db.products.insertMany( [ { item: "card", qty: 15 }, { item: "envelope", qty: 20 }, { item: "stamps" , qty: 30 } ] ); } catch (e) { print (e); }
この操作を実行すると次のドキュメントが返されます。
{ "acknowledged" : true, "insertedIds" : [ ObjectId("562a94d381cb9f1cd6eb0e1a"), ObjectId("562a94d381cb9f1cd6eb0e1b"), ObjectId("562a94d381cb9f1cd6eb0e1c") ] }
ドキュメントに _id
が含まれていなかったため、mongod
は各ドキュメント向けに _id
フィールドを作成して追加し、そのフィールドにユニークな ObjectId()
値を割り当てます。
ObjectId
値は、操作が実行されるマシンと時間に固有であるため、実際の値は例の値と異なる可能性があります。
フィールドを指定して複数のドキュメントを挿入_id
次の例/操作では、insertMany()
を使用して、_id
フィールドを含むドキュメントを挿入しています。コレクション内では重複キー エラーを回避するために、_id
にユニークな値を設定します。
try { db.products.insertMany( [ { _id: 10, item: "large box", qty: 20 }, { _id: 11, item: "small box", qty: 55 }, { _id: 12, item: "medium box", qty: 30 } ] ); } catch (e) { print (e); }
この操作を実行すると次のドキュメントが返されます。
{ "acknowledged" : true, "insertedIds" : [ 10, 11, 12 ] }
_id
など、ユニークインデックスの構成キーに重複値を挿入すると、例外がスローされます。この例外を受け、既存の _id
値を持つドキュメントの挿入を試みます。
try { db.products.insertMany( [ { _id: 13, item: "envelopes", qty: 60 }, { _id: 13, item: "stamps", qty: 110 }, { _id: 14, item: "packing tape", qty: 38 } ] ); } catch (e) { print (e); }
_id: 13
はすでにあるため、次の例外がスローされます。
BulkWriteError({ "writeErrors" : [ { "index" : 0, "code" : 11000, "errmsg" : "E11000 duplicate key error collection: inventory.products index: _id_ dup key: { : 13.0 }", "op" : { "_id" : 13, "item" : "stamps", "qty" : 110 } } ], "writeConcernErrors" : [ ], "nInserted" : 1, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] })
挿入されたドキュメントは 1 つであることに注意してください。_id: 13
の最初のドキュメントは正常に挿入されますが、2 番目の挿入は失敗します。そのため、キューに残っている他のドキュメントも挿入が阻止されます。
ordered
がfalse
に設定されている場合、残りのドキュメントで挿入操作が続行されます。
順序なし挿入
次の例では、_id
フィールドと ordered: false
を伴う複数のドキュメントを挿入しようとしています。ドキュメントの配列には、_id
フィールドが重複している 2 つのドキュメントが含まれています。
try { db.products.insertMany( [ { _id: 10, item: "large box", qty: 20 }, { _id: 11, item: "small box", qty: 55 }, { _id: 11, item: "medium box", qty: 30 }, { _id: 12, item: "envelope", qty: 100}, { _id: 13, item: "stamps", qty: 125 }, { _id: 13, item: "tape", qty: 20}, { _id: 14, item: "bubble wrap", qty: 30} ], { ordered: false } ); } catch (e) { print (e); }
この操作では、次の例外がスローされます。
BulkWriteError({ "writeErrors" : [ { "index" : 2, "code" : 11000, "errmsg" : "E11000 duplicate key error collection: inventory.products index: _id_ dup key: { : 11.0 }", "op" : { "_id" : 11, "item" : "medium box", "qty" : 30 } }, { "index" : 5, "code" : 11000, "errmsg" : "E11000 duplicate key error collection: inventory.products index: _id_ dup key: { : 13.0 }", "op" : { "_id" : 13, "item" : "tape", "qty" : 20 } } ], "writeConcernErrors" : [ ], "nInserted" : 5, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] })
item: "medium box"
と item: "tape"
を伴うドキュメントの挿入は、_id
値が重複しているため、失敗しますが、nInserted
は残りの 5 つのドキュメントが挿入されたことを示しています。
書込み保証の使用
3つのノードから成るレプリカセットにおいて、次の操作は w
の majority
と wtimeout
の 100
を指定します。
try { db.products.insertMany( [ { _id: 10, item: "large box", qty: 20 }, { _id: 11, item: "small box", qty: 55 }, { _id: 12, item: "medium box", qty: 30 } ], { w: "majority", wtimeout: 100 } ); } catch (e) { print (e); }
プライマリと少なくとも 1 つのセカンダリが 100 ミリ秒以内に各書き込み操作を確認すると、次の値が返されます。
{ "acknowledged" : true, "insertedIds" : [ ObjectId("562a94d381cb9f1cd6eb0e1a"), ObjectId("562a94d381cb9f1cd6eb0e1b"), ObjectId("562a94d381cb9f1cd6eb0e1c") ] }
レプリカセット内ですべての必須ノードによる書き込み (write) 操作の確認に必要な合計時間が wtimeout
を超過した場合、wtimeout
期間が経過すると次の writeConcernError
が表示されます。
この操作では以下が返されます。
WriteConcernError({ "code" : 64, "errmsg" : "waiting for replication timed out", "errInfo" : { "wtimeout" : true, "writeConcern" : { "w" : "majority", "wtimeout" : 100, "provenance" : "getLastErrorDefaults" } } })