Overview
このガイドでは、 Scalaドライバーを使用して、1 回のデータベース呼び出しでデータに複数の変更を加える一括書き込み操作を実行する方法を説明します。
ドキュメントを挿入し、複数の他のドキュメントを更新してから、ドキュメント を削除するシナリオを考えてみましょう。 個々のメソッドを使用する場合、各操作には独自のデータベース呼び出しが必要です。
一括書き込み操作 を使用すると、より少ないデータベース呼び出しで複数の書き込み操作を実行できます。 次のレベルで一括書き込み操作を実行できます。
コレクション :
MongoCollection.bulkWrite()メソッドを使用して、単一のコレクションに対して一括書き込み操作を実行できます。このメソッドでは、それぞれの書き込み操作に少なくとも 1 回のデータベース呼び出しが必要です。 例、MongoCollection.bulkWrite()は 1 回の呼び出しで複数のアップデート操作を実行しますが、挿入操作と置換操作の場合はデータベースに 2 回個別の呼び出しを行います。クライアント :アプリケーションがMongoDB Serverバージョン8.0 以降に接続している場合は、
MongoClient.bulkWrite()メソッドを使用して、同じクラスター内の複数のコレクションとデータベースに対して一括書込み操作を実行できます。このメソッドは、1 回のデータベース呼び出しですべての書き込み操作を実行します。
コレクションの一括書込み (write)
一括書き込み操作には、1 つ以上の書き込み操作が含まれます。 コレクションレベルで一括書き込み操作を実行するには、WriteModel ドキュメントの Seq を MongoCollection.bulkWrite() メソッドに渡します。 WriteModel は 書込み操作を表すモデルです。
実行する書込み操作ごとに、WriteModel から継承する次のいずれかのクラスのインスタンスを作成します。
InsertOneModelUpdateOneModelUpdateManyModelReplaceOneModelDeleteOneModelDeleteManyModel
次に、これらのインスタンスのリストをbulkWrite()メソッドに渡します。
次のセクションでは、前述のクラスのインスタンスを作成して使用する方法を示します。 「一括操作の実行 」セクションでは、モデルのリストをbulkWrite()メソッドに渡して一括操作を実行する方法が説明されています。
サンプル データ
このセクションの例では、Atlasサンプルデータセット の sample_restaurantsデータベースの restaurantsコレクションを使用します。Scalaアプリケーションからこのコレクションにアクセスするには、Atlas クラスターに接続する MongoClient を作成し、database 変数と collection 変数に次の値を割り当てます。
val database: MongoDatabase = mongoClient.getDatabase("sample_restaurants") val collection: MongoCollection[Document] = database.getCollection("restaurants")
MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、MongoDBを使い始めるガイドを参照してください。
挿入操作
挿入操作を実行するには、 InsertOneModelインスタンスを作成し、挿入するドキュメントを指定します。
次の例では、 InsertOneModelのインスタンスを作成しています。
val insertOneModel = InsertOneModel( Document("name" -> "Blue Moon Grill", "borough" -> "Brooklyn", "cuisine" -> "American") )
複数のドキュメントを挿入するには、ドキュメントごとにInsertOneModelのインスタンスを作成します。
重要
一括操作を実行する場合、 InsertOneModelはコレクション内にすでに存在する_idを含むドキュメントを挿入できません。 この状況では、ドライバーはMongoBulkWriteExceptionをスローします。
アップデート操作
ドキュメントを更新するには、 UpdateOneModelのインスタンスを作成し、次の引数を渡します。
コレクション内のドキュメントをマッチングするために使用される基準を指定するクエリフィルター。
実行する更新操作。更新操作の詳細については、 MongoDB Serverマニュアルのフィールド更新演算子ガイドを参照してください。
次の例では、 UpdateOneModelのインスタンスを作成しています。
val updateOneFilter = equal("name", "White Horse Tavern") val updateOneDoc = set("borough", "Queens") val updateOneModel = UpdateOneModel(updateOneFilter, updateOneDoc)
複数のドキュメントが UpdateOneModelインスタンスで指定されたクエリフィルターに一致する場合、この操作最初の結果が更新されます。 次のコードに示すように、ドライバーが 更新操作 を実行する前に、一致したドキュメントに順序を適用するために、UpdateOptionsインスタンスで並べ替えを指定できます。
val options = UpdateOptions.sort(ascending("name"))
複数のドキュメントを更新するには、UpdateManyModel のインスタンスを作成し、UpdateOneModel と同じ引数を渡します。UpdateManyModelクラスは、クエリフィルターに一致するすべてのドキュメントのアップデートを指定します。
次の例では、 UpdateManyModelのインスタンスを作成しています。
val updateManyFilter = equal("name", "Wendy's") val updateManyDoc = set("cuisine", "Fast food") val updateManyModel = UpdateManyModel(updateManyFilter, updateManyDoc)
置換操作
置換操作、指定されたドキュメントのすべてのフィールドと値が削除され、指定した新しいフィールドと値に置き換えられます。 置換操作 を実行するには、ReplaceOneModel のインスタンスを作成し、次の引数を渡します。
コレクション内のドキュメントをマッチングするために使用される基準を指定するクエリフィルター
挿入する新しいフィールドと値を指定する置換ドキュメント
次の例では、 ReplaceOneModelのインスタンスを作成しています。
val replaceFilter = equal("name", "Cooper Town Diner") val replaceDoc = Document("name" -> "Smith Town Diner", "borough" -> "Brooklyn", "cuisine" -> "American") val replaceOneModel = ReplaceOneModel(replaceFilter, replaceDoc)
複数のドキュメントが ReplaceOneModelインスタンスで指定されたクエリフィルターに一致する場合、その操作は最初の結果を置き換えます。 次のコードに示すように、ドライバーが置換操作を実行する前に、一致したドキュメントに順序を適用するために、ReplaceOptionsインスタンスで並べ替えを指定できます。
val options = ReplaceOptions.sort(ascending("name"))
Tip
複数のドキュメントの置換
複数のドキュメントを置き換えるには、ドキュメントごとにReplaceOneModelのインスタンスを作成します。
削除操作
ドキュメントを削除するには、 DeleteOneModelのインスタンスを作成し、削除するドキュメントを指定するクエリフィルターを渡します。 DeleteOneModelインスタンスには、クエリフィルターに一致する最初のドキュメントのみを削除するための手順が記載されています。
次の例では、 DeleteOneModelのインスタンスを作成しています。
val deleteOneModel = DeleteOneModel(equal("name", "Morris Park Bake Shop"))
複数のドキュメントを削除するには、 DeleteManyModelのインスタンスを作成し、削除するドキュメントを指定してクエリフィルターを渡します。 DeleteManyModelのインスタンスには、クエリフィルターに一致するすべてのドキュメントを削除するための手順が表示されます。
次の例では、 DeleteManyModelのインスタンスを作成しています。
val deleteManyModel = DeleteManyModel(equal("cuisine", "Experimental"))
一括操作の実行
実行する操作ごとにモデルインスタンスを定義した後、それらのモデルを含む SeqインスタンスをMongoCollection.bulkWrite() メソッドに渡します。デフォルトでは 、メソッドはモデルのリストで指定された順序で操作を実行します。
次の例では、 bulkWrite()メソッドを使用して複数の書込み操作を実行します。
val insertOneModel = InsertOneModel( Document("name" -> "Red's Pizza", "borough" -> "Brooklyn", "cuisine" -> "Pizzeria") ) val updateOneModel = UpdateOneModel(equal("name", "Moonlit Tavern"), set("borough", "Queens")) val deleteManyModel = DeleteManyModel(equal("name", "Crepe")) val writes = Seq(insertOneModel, updateOneModel, deleteManyModel) val observable = collection.bulkWrite(writes) observable.subscribe( (result: BulkWriteResult) => println(s"Success: $result"), (error: Throwable) => println(s"Error: ${error.getMessage}"), () => println("Completed") )
Success: AcknowledgedBulkWriteResult{insertedCount=1, matchedCount=1, removedCount=1, modifiedCount=1, upserts=[], inserts=[BulkWriteInsert{index=0, id=BsonObjectId{value=...}}]} Completed
いずれかの書き込み操作が失敗した場合、 Scalaドライバーは BulkWriteError を発生させ、それ以上の操作を実行しません。 BulkWriteError は、失敗した操作と例外に関する詳細を含む details アイテムを提供します。
注意
ドライバーが一括操作を実行する場合、ターゲット コレクションの書込み保証 (write concern) が使用されます。 ドライバーは、実行順序に関係なく、すべての操作を試行した後にすべての書込み保証 (write concern) エラーを報告します。
一括書き込みをカスタマイズする
オプションで、MongoCollection.bulkWrite() メソッドは BulkWriteOptions パラメータを受け入れます。このパラメータは、 一括書込み操作を構成するために使用できるオプションを指定します。オプションを指定しない場合、ドライバーはデフォルト設定で一括操作を実行します。書込み操作の動作を変更するには、クラスインスタンスをbulkWrite() メソッドの最後の引数として渡します。
次の表では、 BulkWriteOptionsインスタンスを構成するために使用できる setter メソッドについて説明します。
方式 | 説明 |
|---|---|
|
|
| アップデート操作がドキュメント検証をバイパスするかどうかを指定します。これにより、スキーマ検証要件を満たさないドキュメントを更新することができます(存在する場合)。スキーマ検証の詳細については、 MongoDB Serverマニュアルの「 スキーマバリデーション 」を参照してください。デフォルトは |
| 操作に添付するコメントを設定します。 |
| 操作の最上位変数を設定するためのパラメーター名と値のマップを提供します。値は、ドキュメントフィールドを参照しない定数または閉じた式である必要があります。 |
次のコードでは、オプションを作成し、ordered オプションを false に設定して、順序なしの一括書き込みを指定します。 次に、この例ではbulkWrite() メソッドを使用して 一括操作 を実行します。
val options = BulkWriteOptions().ordered(false) val observable = collection.bulkWrite(writes, options)
順序付けなし一括書き込み 内のいずれかの書き込み操作が失敗した場合、 Scalaドライバーはすべての操作を試行した後にのみエラーを報告します。
注意
順序なしの一括操作では、実行順序は保証されません。 この順序は、ランタイムを最適化するために一覧表示する方法とは異なる場合があります。
戻り値
bulkWrite() メソッドは、BulkWriteResult を含む SingleObservableオブジェクトを返します。 Observable にサブスクライブし、次の方法を使用することで、BulkWriteResultインスタンスからの情報にアクセスできます。
方式 | 説明 |
|---|---|
| サーバーが書込み (write) 操作を確認したかどうかを示します。 |
| 削除されたドキュメントの数(存在する場合)。 |
| 挿入されたドキュメントの数(存在する場合)。 |
| 挿入されたドキュメントのリスト(存在する場合)。 |
| アップデートに一致したドキュメントの数(該当する場合)。 |
| 変更されたドキュメントの数(存在する場合)。 |
| アップサートされたドキュメントの一覧(存在する場合)。 |
クライアント一括書込み (write)
MongoDB Server 8.0 以降を実行中配置に接続する場合、MongoClient.bulkWrite() メソッドを使用して同じクラスター内の複数のデータベースとコレクションに書込み (write) できます。 MongoClient.bulkWrite() メソッドは、1 回の呼び出しですべての書き込み操作を実行します。
MongoClient.bulkWrite() メソッドは、さまざまな書込み操作を表す 1 つ以上の ClientNamespacedWriteModel インスタンスを含む List を受け取ります。インスタンスメソッドを使用して、ClientNamespacedWriteModel インターフェースのインスタンスを構築できます。例、ClientNamespacedInsertOneModel のインスタンスは1 つのドキュメントを挿入する操作を表します。このモデルは ClientNamespacedWriteModel.insertOne() メソッドを使用して作成できます。
次の表では、モデルとそれに対応するインスタンスメソッドについて説明しています。
モデル | インスタンス メソッド | 説明 | パラメーター |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
次のセクションでは、モデルを作成し、クライアントのbulkWrite() メソッドを使用する方法の例をいくつか示します。
挿入操作
この例では、 2 つのドキュメントを挿入する指示を含むモデルを作成する方法を示しています。 1 つのドキュメントはdb.peopleコレクションに挿入され、もう 1 つのドキュメントはdb.thingsコレクションに挿入されます。 MongoNamespaceインスタンスは、各書込み操作が適用されるターゲットデータベースとコレクションを定義します。
val personToInsert = ClientNamespacedWriteModel.insertOne( MongoNamespace("db", "people"), Document("name" -> "Julia Smith") ) val thingToInsert = ClientNamespacedWriteModel.insertOne( MongoNamespace("db", "things"), Document("object" -> "washing machine") );
アップデート操作
次の例は、bulkWrite() メソッドを使用して、db.people コレクションと db.things コレクション内の既存のドキュメントを更新する方法を示しています。
val personUpdate = ClientNamespacedWriteModel.updateOne( MongoNamespace("db", "people"), equal("name", "Freya Polk"), inc("age", 1) ) val thingUpdate = ClientNamespacedWriteModel.updateMany( MongoNamespace("db", "things"), equal("category", "electronic"), set("manufacturer", "Premium Technologies") )
この例では、peopleコレクションで name 値が "Freya Polk" であるドキュメントで、ageフィールドの値を 1 ずつ増加させます。また、thingsコレクション内で category 値が "electronic" であるすべてのドキュメントの manufacturerフィールドの値を "Premium Technologies" に設定します。
複数のドキュメントが ClientNamespacedUpdateOneModelインスタンスで指定されたクエリフィルターに一致する場合、この操作最初の結果が更新されます。次のコードに示すように、 ClientUpdateOneOptionsインスタンスでソート順序を指定して、ドライバーが 更新操作 を実行する前に一致したドキュメントに順序を適用できます。
val options = ClientUpdateOneOptions .clientUpdateOneOptions() .sort(ascending("_id"))
置換操作
次の例は、 db.people コレクションと db.things コレクション内の既存のドキュメントを置き換えるためのモデルを作成する方法を示しています。
val personReplacement = ClientNamespacedWriteModel.replaceOne( MongoNamespace("db", "people"), equal("_id", 1), Document("name" -> "Frederic Hilbert") ) val thingReplacement = ClientNamespacedWriteModel.replaceOne( MongoNamespace("db", "things"), equal("_id", 1), Document("object" -> "potato") )
上記のコード例では、次のドキュメントを新しいドキュメントに置き換えます。
_id値が1であるpeopleコレクション内のドキュメント_id値が1であるthingsコレクション内のドキュメント
複数のドキュメントが ClientNamespacedReplaceOneModelインスタンスで指定されたクエリフィルターに一致する場合、その操作は最初の結果を置き換えます。次のコードに示すように、ClientReplaceOneOptionsインスタンスでソート順序を指定して、ドライバーが置換操作を実行する前に一致したドキュメントに順序を適用できます。
val options = ClientReplaceOneOptions .clientReplaceOneOptions() .sort(ascending("_id"))
一括操作の実行
実行する操作ごとに ClientNamespacedWriteModelインスタンスを定義した後、これらのインスタンスのリストをクライアントの bulkWrite() メソッドに渡します。デフォルトでは 、メソッドは指定された順序で操作を実行します。
次の例では、 bulkWrite()メソッドを使用して複数の書込み操作を実行します。
val peopleNamespace = MongoNamespace("db", "people") val thingsNamespace = MongoNamespace("db", "things") val writeModels = List( ClientNamespacedWriteModel.insertOne( peopleNamespace, Document("name" -> "Corey Kopper") ), ClientNamespacedWriteModel.replaceOne( thingsNamespace, equal("_id", 1), Document("object" -> "potato") ) ) val observable = mongoClient.bulkWrite(writeModels) observable.subscribe( (result: ClientBulkWriteResult) => println(result.toString), (error: Throwable) => println(s"Error: ${error.getMessage}"), () => println("Completed") )
AcknowledgedSummaryClientBulkWriteResult{insertedCount=1, matchedCount=1, ...}
書き込み操作のいずれかが失敗した場合、ドライバーは ClientBulkWriteException を発生させ、それ以上の個々の操作を実行しません。ClientBulkWriteException には、障害に関する情報を提供する ClientBulkWriteException.getWriteErrors() メソッドを使用してアクセスできる BulkWriteError が含まれています。
一括書き込みをカスタマイズする
ClientBulkWriteOptions のインスタンスをbulkWrite() メソッドに渡して、ドライバーが 一括書込み操作を実行する方法をカスタマイズできます。
実行順序
デフォルトでは 、ドライバーは指定された順序で個々の操作を一括操作で実行します。ドライバーは、エラーが発生するまで、または合計一括操作が正常に完了するまで操作を実行します。
ただし、ClientBulkWriteOptionsインスタンスを作成するときに false を ordered() メソッドに渡して、ドライバーに書込み操作を順序なしで実行させることができます。false を渡すと、ドライバーは 1 つの操作でエラーが発生した場合でも、 一括書込み操作内のすべての書込み操作を実行しようとします。
次のコードは、ClientBulkWriteOptions のインスタンスで ordered オプションを false に設定し、一括書き込み操作を実行して複数のドキュメントを挿入します。
val namespace = MongoNamespace("db", "people") val options = ClientBulkWriteOptions.clientBulkWriteOptions().ordered(false) val writeModels = List( ClientNamespacedWriteModel.insertOne(namespace, Document("_id" -> 1, "name" -> "Rudra Suraj")), // Causes a duplicate key error ClientNamespacedWriteModel.insertOne(namespace, Document("_id" -> 1, "name" -> "Mario Bianchi")), ClientNamespacedWriteModel.insertOne(namespace, Document("name" -> "Wendy Zhang")) ) val observable = mongoClient.bulkWrite(writeModels, options)
書込み操作は順序付けられていないため、重複キーを持つドキュメントを挿入する書込み操作でエラーが発生しても、ドライバーはエラー以外のすべての操作を実行します。
詳細情報
個々の書込み操作を実行する方法については、次のガイドを参照してください。
API ドキュメント
このガイドで説明したメソッドや型の詳細については、次の API ドキュメントを参照してください。
クライアント一括書込み (write)