Overview
このガイドでは、 PyMongoを使用して一括操作を実行する方法を学習できます。一括操作では、単一のメソッドで複数の書込み (write) 操作を実行することで、サーバーへの呼び出し回数を減らします。
Collection クラスと MongoClient クラスはどちらも bulk_write() メソッドを提供します。Collectionインスタンスで bulk_write() を呼び出すと、1 つのコレクションに対して複数の書き込み操作を実行できます。MongoClientインスタンスで bulk_write() を呼び出すと、複数の名前空間にわたって一括書込みを実行できます。MongoDBでは、名前空間はデータベース名とコレクション名で形式<database>.<collection> で構成されています。
重要
MongoClientインスタンスで一括操作を実行するには、アプリケーションが次の要件を満たしていることを確認します。
PyMongo v4.9 以降を使用
MongoDB Server v8.0 以降に接続
サンプル データ
このガイドの例では、Atlasサンプルデータセット の sample_restaurants.restaurants コレクションと sample_mflix.movies コレクションを使用します。MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、 「 PyMongoを使い始める 」チュートリアルを参照してください。
書込み (write) 操作を定義する
実行する書込み操作ごとに、次のいずれかの操作クラスのインスタンスを作成します。
InsertOneUpdateOneUpdateManyReplaceOneDeleteOneDeleteMany
次に、これらのインスタンスのリストをbulk_write()メソッドに渡します。
重要
次のコードに示すように、書込み (write)操作クラスをアプリケーションファイルに必ずインポートしてください。
from pymongo import InsertOne, UpdateOne, UpdateMany, ReplaceOne, DeleteOne, DeleteMany
次のセクションでは、コレクションおよびクライアントの一括操作を実行するために使用できる前述のクラスのインスタンスを作成する方法を示します。
挿入操作
挿入操作を実行するには、InsertOne のインスタンスを作成し、挿入するドキュメントを指定します。次のキーワード引数を InsertOne コンストラクターに渡します。
namespace:ドキュメントを挿入する名前空間空間。この引数は、単一のコレクションに対して 一括操作 を実行する場合は任意です。document: 挿入するドキュメント。
次の例では、 InsertOneのインスタンスを作成しています。
operation = InsertOne( namespace="sample_restaurants.restaurants", document={ "name": "Mongo's Deli", "cuisine": "Sandwiches", "borough": "Manhattan", "restaurant_id": "1234" } )
カスタムクラスのインスタンスをコンストラクターに渡すことで、InsertOne のインスタンスを作成することもできます。これにより、型チェックツールを使用している場合、追加の型の安全性が確保されます。渡すインスタンスは、TypedDictクラスから継承する必要があります。
注意
Python 3.7 以前の TypedDiction
TypedDictionクラスは typing モジュールにあります。このモジュールはPython 3.8 以降でのみ利用可能です。Pythonの以前のバージョンで TypedDictクラスを使用するには、 mapping_extentionsパッケージをインストールします。
次の例では、型の安全性を高めるためにカスタムクラスを使用して InsertOneインスタンスを構築します。
class Restaurant (TypedDict): name: str cuisine: str borough: str restaurant_id: str operation = pymongo.InsertOne(Restaurant( name="Mongo's Deli", cuisine="Sandwiches", borough="Manhattan", restaurant_id="1234"))
複数のドキュメントを挿入するには、ドキュメントごとにInsertOneのインスタンスを作成します。
注意
_id フィールドは一意である必要があります
MongoDBコレクションでは、各ドキュメントに一意の値を持つ _idフィールドが含まれている必要があります。
_idフィールドに値を指定する場合は、その値がコレクション全体で一意であることを確認する必要があります。値を指定しない場合、ドライバーはフィールドに一意の ObjectId 値を自動的に生成します。
一意性を確保するために、ドライバーが _id 値を自動的に生成することをお勧めします。重複した _id 値はユニークインデックス制約に違反するため、ドライバーはエラーを返します。
アップデート操作
ドキュメントを更新するには、 UpdateOneのインスタンスを作成し、次の引数を渡します。
namespace: アップデートを実行する名前空間空間。この引数は、単一のコレクションに対して 一括操作 を実行する場合は任意です。filter: コレクション内のドキュメントをマッチングするために使用される基準を指定するクエリフィルター。
UpdateOne はクエリフィルターに一致する最初のドキュメントを更新します。
次の例では、 UpdateOneのインスタンスを作成しています。
operation = UpdateOne( namespace="sample_restaurants.restaurants", filter={ "name": "Mongo's Deli" }, update={ "$set": { "cuisine": "Sandwiches and Salads" }} )
複数のドキュメントを更新するには、 UpdateManyのインスタンスを作成し、同じ引数で渡します。 UpdateManyは、クエリフィルターに一致するすべてのドキュメントを更新します。
次の例では、 UpdateManyのインスタンスを作成しています。
operation = UpdateMany( namespace="sample_restaurants.restaurants", filter={ "name": "Mongo's Deli" }, update={ "$set": { "cuisine": "Sandwiches and Salads" }} )
置換操作
置換操作、指定されたドキュメントのすべてのフィールドと値が削除され、新しいフィールドと値に置き換えられます。置換操作を実行するには、ReplaceOne のインスタンスを作成し、次の引数を渡します。
namespace: 置換操作を実行する名前空間空間。この引数は、単一のコレクションに対して 一括操作 を実行する場合は任意です。filter: 置き換えるドキュメントを一致させるために使用される基準を指定するクエリフィルター。replacement: 一致するドキュメントに保存する新しいフィールドと値を含むドキュメント。
次の例では、 ReplaceOneのインスタンスを作成しています。
operation = ReplaceOne( namespace="sample_restaurants.restaurants", filter={ "restaurant_id": "1234" }, replacement={ "name": "Mongo's Pizza", "cuisine": "Pizza", "borough": "Brooklyn", "restaurant_id": "5678" } )
カスタムクラスのインスタンスをコンストラクターに渡すことで、ReplaceOne のインスタンスを作成することもできます。これにより、型チェックツールを使用している場合、追加の型の安全性が確保されます。渡すインスタンスは、TypedDictクラスから継承する必要があります。
注意
Python 3.7 以前の TypedDiction
TypedDictionクラスは typing モジュールにあります。このモジュールはPython 3.8 以降でのみ利用可能です。Pythonの以前のバージョンで TypedDictクラスを使用するには、 mapping_extentionsパッケージをインストールします。
次の例では、型の安全性を高めるためにカスタムクラスを使用して ReplaceOneインスタンスを構築します。
class Restaurant (TypedDict): name: str cuisine: str borough: str restaurant_id: str operation = pymongo.ReplaceOne( { "restaurant_id": "1234" }, Restaurant(name="Mongo's Pizza", cuisine="Pizza", borough="Brooklyn", restaurant_id="5678") )
複数のドキュメントを置き換えるには、ドキュメントごとにReplaceOneのインスタンスを作成する必要があります。
削除操作
ドキュメントを削除するには、DeleteOne のインスタンスを作成し、次の引数を渡します。
namespace:ドキュメントを削除する名前空間空間。この引数は、単一のコレクションに対して 一括操作 を実行する場合は任意です。filter: 削除するドキュメントを一致させるために使用される条件を指定するクエリフィルター。
DeleteOne はクエリフィルターに一致する最初のドキュメントのみを削除します。
次の例では、 DeleteOneのインスタンスを作成しています。
operation = DeleteOne( namespace="sample_restaurants.restaurants", filter={ "restaurant_id": "5678" } )
複数のドキュメントを削除するには、DeleteMany のインスタンスを作成し、削除するドキュメントを指定する名前空間とクエリフィルターを渡します。DeleteMany は、クエリフィルターに一致するすべてのドキュメントを削除します。
次の例では、 DeleteManyのインスタンスを作成しています。
operation = DeleteMany( namespace="sample_restaurants.restaurants", filter={ "name": "Mongo's Deli" } )
bulk_write() メソッドの呼び出し
実行する操作ごとにクラスインスタンスを定義したら、これらのインスタンスのリストを bulk_write() メソッドに渡します。単一のコレクションに書込むには Collectionインスタンスで bulk_write() メソッドを呼び出し、複数の名前空間に書込むには MongoClientインスタンスの メソッドを呼び出します。
Collection で呼び出された書込み操作のいずれかが失敗した場合、 PyMongo はBulkWriteError を発生させ、それ以上の操作を実行しません。BulkWriteError は、失敗した操作を含む details 属性と例外に関する詳細を提供します。
MongoClient で呼び出された書込み操作のいずれかが失敗した場合、 PyMongo はClientBulkWriteException を発生させ、それ以上の操作を実行しません。ClientBulkWriteException は、例外に関する情報を含む error 属性を提供します。
注意
PyMongo が一括操作を実行する場合、操作が実行中いるコレクションまたはクライアントの write_concern が使用されます。MongoClient.bulk_write() メソッドを使用して、操作に書込み保証 (write concern)を設定することもできます。ドライバーは、実行順序に関係なく、すべての操作を試行した後にすべての書込み保証 (write concern)エラーを報告します。
書込み保証 (write concern) の詳細については、 MongoDB Serverマニュアルの「 書込み保証 (write concern) 」を参照してください。
コレクション一括書込みの例
次の例では、Collectionインスタンスで bulk_write() メソッドを使用して、restaurantsコレクションに対して複数の書込み操作を実行します。対応するコードを表示するには、Synchronous タブまたは Asynchronousタブを選択します。
operations = [ InsertOne( document={ "name": "Mongo's Deli", "cuisine": "Sandwiches", "borough": "Manhattan", "restaurant_id": "1234" } ), InsertOne( document={ "name": "Mongo's Deli", "cuisine": "Sandwiches", "borough": "Brooklyn", "restaurant_id": "5678" } ), UpdateMany( filter={ "name": "Mongo's Deli" }, update={ "$set": { "cuisine": "Sandwiches and Salads" }} ), DeleteOne( filter={ "restaurant_id": "1234" } ) ] results = restaurants.bulk_write(operations) print(results)
BulkWriteResult({'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 2, 'nModified': 2, 'nRemoved': 1, 'upserted': []}, acknowledged=True)
operations = [ InsertOne( document={ "name": "Mongo's Deli", "cuisine": "Sandwiches", "borough": "Manhattan", "restaurant_id": "1234" } ), InsertOne( document={ "name": "Mongo's Deli", "cuisine": "Sandwiches", "borough": "Brooklyn", "restaurant_id": "5678" } ), UpdateMany( filter={ "name": "Mongo's Deli" }, update={ "$set": { "cuisine": "Sandwiches and Salads" }} ), DeleteOne( filter={ "restaurant_id": "1234" } ) ] results = await restaurants.bulk_write(operations) print(results)
BulkWriteResult({'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 2, 'nModified': 2, 'nRemoved': 1, 'upserted': []}, acknowledged=True)
クライアント一括書込みの例
次の例では、MongoClientインスタンスで bulk_write() メソッドを使用して、sample_restaurants.restaurants と sample_mflix.movies の名前空間に対して複数の書込み操作を実行します。対応するコードを表示するには、Synchronous タブまたは Asynchronousタブを選択します。
operations = [ InsertOne( namespace="sample_mflix.movies", document={ "title": "Minari", "runtime": 217, "genres": ["Drama", "Comedy"] } ), UpdateOne( namespace="sample_mflix.movies", filter={ "title": "Minari" }, update={ "$set": { "runtime": 117 }} ), DeleteMany( namespace="sample_restaurants.restaurants", filter={ "cuisine": "French" } ) ] results = client.bulk_write(operations) print(results)
ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1, 'nModified': 1, 'nDeleted': 344, 'insertResults': {}, 'updateResults': {}, 'deleteResults': {}}, acknowledged=True, verbose=False)
operations = [ InsertOne( namespace="sample_mflix.movies", document={ "title": "Minari", "runtime": 217, "genres": ["Drama", "Comedy"] } ), UpdateOne( namespace="sample_mflix.movies", filter={ "title": "Minari" }, update={ "$set": { "runtime": 117 }} ), DeleteMany( namespace="sample_restaurants.restaurants", filter={ "cuisine": "French" } ) ] results = await client.bulk_write(operations) print(results)
ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1, 'nModified': 1, 'nDeleted': 344, 'insertResults': {}, 'updateResults': {}, 'deleteResults': {}}, acknowledged=True, verbose=False)
一括書き込み操作をカスタマイズ
オプションで、bulk_write() メソッドは追加のパラメーターを受け入れます。これらのパラメーターは、 一括書込み操作を構成するために使用できるオプションを表します。
コレクション一括書込みオプション
次の表では、Collection.bulk_write() メソッドに渡すことができるオプションについて説明しています。
プロパティ | 説明 |
|---|---|
|
|
| 操作がドキュメントレベルの検証をバイパスするかどうかを指定します。詳細については、 MongoDB Serverマニュアルの「 スキーマバリデーション 」を参照してください。デフォルトは |
|
|
| 操作に添付するコメント。 詳細については、MongoDB Server マニュアルの 「削除コマンド フィールドのガイド」 を参照してください。 |
| パラメーター名と値のマップ。 値は、ドキュメント フィールドを参照しない定数または閉じた式である必要があります。 詳細については、MongoDB Server マニュアルのlet ステートメントを参照してください。 |
次の例では、前述のコレクション一括書き込みの例からbulk_write() メソッドを呼び出しますが、ordered オプションをFalse に設定します。対応するコードを表示するには、Synchronous タブまたは Asynchronousタブを選択します。
results = restaurants.bulk_write(operations, ordered=False)
results = await restaurants.bulk_write(operations, ordered=False)
順序なし一括書き込み 内のいずれかの書き込み操作が失敗した場合、PyMongo はすべての操作を試行した後にのみエラーを報告します。
注意
順序なしの一括操作では、実行順序は保証されません。 この順序は、ランタイムを最適化するために一覧表示する方法とは異なる場合があります。
クライアント一括書込みオプション
次の表では、MongoClient.bulk_write() メソッドに渡すことができるオプションについて説明しています。
プロパティ | 説明 |
|---|---|
|
|
|
|
| 操作が成功させる各操作の詳細な結果を返すかどうかを指定します。 |
| 操作がドキュメントレベルの検証をバイパスするかどうかを指定します。詳細については、 MongoDB Serverマニュアルの「 スキーマバリデーション 」を参照してください。デフォルトは |
| 操作に添付するコメント。 詳細については、MongoDB Server マニュアルの 「削除コマンド フィールドのガイド」 を参照してください。 |
| パラメーター名と値のマップ。 値は、ドキュメント フィールドを参照しない定数または閉じた式である必要があります。 詳細については、MongoDB Server マニュアルのlet ステートメントを参照してください。 |
| 一括操作に使用する書込み保証 (write concern)を指定します。詳細については、 MongoDB Serverマニュアルの「 書込み保証 」を参照してください。 |
次の例では、前述のクライアント一括書き込みの例からbulk_write() メソッドを呼び出しますが、verbose_results オプションをTrue に設定します。対応するコードを表示するには、Synchronous タブまたは Asynchronousタブを選択します。
results = client.bulk_write(operations, verbose_results=True)
ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1, 'nModified': 1, 'nDeleted': 344, 'insertResults': {0: InsertOneResult(ObjectId('...'), acknowledged=True)}, 'updateResults': {1: UpdateResult({'ok': 1.0, 'idx': 1, 'n': 1, 'nModified': 1}, acknowledged=True)}, 'deleteResults': {2: DeleteResult({'ok': 1.0, 'idx': 2, 'n': 344}, acknowledged=True)}}, acknowledged=True, verbose=True)
results = await client.bulk_write(operations, verbose_results=True)
ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1, 'nModified': 1, 'nDeleted': 344, 'insertResults': {0: InsertOneResult(ObjectId('...'), acknowledged=True)}, 'updateResults': {1: UpdateResult({'ok': 1.0, 'idx': 1, 'n': 1, 'nModified': 1}, acknowledged=True)}, 'deleteResults': {2: DeleteResult({'ok': 1.0, 'idx': 2, 'n': 344}, acknowledged=True)}}, acknowledged=True, verbose=True)
Return Values
このセクションでは、次の一括操作メソッドの戻り値について説明します。
コレクション一括書き込みの戻り値
Collection.bulk_write()メソッドはBulkWriteResultオブジェクトを返します。 BulkWriteResultオブジェクトには次のプロパティが含まれています。
プロパティ | 説明 |
|---|---|
| サーバーが書込み (write) 操作を確認したかどうかを示します。 |
| サーバーによって返された未加工の一括API の結果です。 |
| 削除されたドキュメントの数(存在する場合)。 |
| 挿入されたドキュメントの数(存在する場合)。 |
| アップデートに一致したドキュメントの数(該当する場合)。 |
| 変更されたドキュメントの数(存在する場合)。 |
| アップサートされたドキュメントの数(存在する場合)。 |
| 操作のインデックスとアップサートされたドキュメントの |
クライアント一括書き込みの戻り値
MongoClient.bulk_write()メソッドはClientBulkWriteResultオブジェクトを返します。 ClientBulkWriteResultオブジェクトには次のプロパティが含まれています。
プロパティ | 説明 |
|---|---|
| サーバーが書込み (write) 操作を確認したかどうかを示します。 |
| サーバーによって返された未加工の一括API の結果です。 |
| 成功した削除操作とその結果のマップ。 |
| 削除されたドキュメントの数(存在する場合)。 |
| 返される結果が詳細であるかどうかを示します。 |
| 成功した挿入操作とその結果のマップ。 |
| 挿入されたドキュメントの数(存在する場合)。 |
| アップデートに一致したドキュメントの数(該当する場合)。 |
| 変更されたドキュメントの数(存在する場合)。 |
| 成功した更新操作とその結果のマップ。 |
| アップサートされたドキュメントの数(存在する場合)。 |
トラブルシューティング
クライアント タイプの注釈
MongoClientオブジェクトに型注釈を追加しない場合、型チェッカーに次のようなエラーが表示される場合があります。
from pymongo import MongoClient client = MongoClient() # error: Need type annotation for "client"
解決策としては、MongoClientオブジェクトを client: MongoClient または client: MongoClient[Dict[str, Any]] として注釈を付けることです。
互換性のないタイプ
型のヒントとして MongoClient を指定しているが、ドキュメント、キー、値のデータ型を含めない場合、型チェッカーに次のようなエラーが表示される場合があります。
error: Dict entry 0 has incompatible type "str": "int"; expected "Mapping[str, Any]": "int"
解決策としては、次のタイプのヒントを MongoClientオブジェクトに追加することです。
client: MongoClient[Dict[str, Any]]
詳細情報
個々の書込み操作を実行する方法については、次のガイドを参照してください。
API ドキュメント
このガイドで説明したメソッドや型の詳細については、次の API ドキュメントを参照してください。