これを処理し、効率的な方法で多くのドキュメントを「挿入/更新」するより良い方法は、一括操作 APIを使用してすべてを「バッチ」で送信し、すべてを効率的に送信し、確認で「単一の応答」を受信することです。
これは 2 つの方法で処理できます。
まず、主キーまたは他のインデックスの「重複エラー」を無視するには、「順序付けされていない」形式の操作を使用できます。
bulk = pymongo.bulk.BulkOperationBuilder(collection,ordered=False)
for doc in docs:
bulk.insert(doc)
response = bulk.execute()
そこにある「UnOrdered」またはfalse
引数は、操作が任意の順序で実行でき、「全体」のバッチが完了し、実際のエラーが単に応答で「報告」されることを意味します。したがって、これは基本的に重複を「無視」して先に進むための 1 つの方法です。
代替アプローチはほとんど同じですが、「アップサート」機能を次のように使用し$setOnInsert
ます。
bulk = pymongo.bulk.BulkOperationBuilder(collection,ordered=True)
for doc in docs:
bulk.find({ "_id": doc["_id"] }).upsert().updateOne({
"$setOnInsert": doc
})
response = bulk.execute()
これにより、「クエリ」部分.find()
は、ドキュメントの「主キー」または代わりに「一意のキー」を使用して、ドキュメントの存在をクエリするために使用されます。一致するものが見つからない場合は、新しいドキュメントが作成されて「アップサート」が発生します。すべての変更内容は内部$setOnInsert
にあるため、"アップサート" が発生した場合、ドキュメント フィールドはここでのみ変更されます。それ以外の場合、ドキュメントが「一致」している間、この演算子の下に保持されているデータに関して実際には何も変更されません。
この場合の「順序付き」とは、すべてのステートメントが実際に作成された「同じ」順序でコミットされることを意味します。また、ここでの「エラー」は、(エラーが発生した時点で) 更新を停止し、それ以上の操作が行われないようにします。コミットします。これはオプションですが、後のステートメントが前のステートメントのデータを「複製」する通常の「複製」動作にはおそらくお勧めです。
したがって、より効率的な書き込みのために、一般的な考え方は、「バルク」API を使用し、それに応じてアクションを構築することです。ここでの選択は、ソースからの「挿入順序」が重要かどうかにかかっています。
もちろん、新しいドライバー リリースで実際に「一括」操作を使用する場合も、同じ"ordered"=False
操作が適用されます。insert_many
しかし、単純な API と操作を「組み合わせる」ことができる一般的なインターフェースに固執することで、より柔軟になります。