Overview
このガイドでは、 Scalaドライバーを使用して、1 回のデータベース呼び出しでデータに複数の変更を加える一括書き込み操作を実行する方法を説明します。
ドキュメントを挿入し、複数の他のドキュメントを更新してから、ドキュメント を削除するシナリオを考えてみましょう。 個々のメソッドを使用する場合、各操作には独自のデータベース呼び出しが必要です。
一括書き込み操作 を使用すると、より少ないデータベース呼び出しで複数の書き込み操作を実行できます。 次のレベルで一括書き込み操作を実行できます。
Collection: You can use the
MongoCollection.bulkWrite()method to perform bulk write operations on a single collection. In this method, each kind of write operation requires at least one database call. For example,MongoCollection.bulkWrite()puts multiple update operations in one call, but makes two separate calls to the database for an insert operation and a replace operation.Client: If your application connects to MongoDB Server version 8.0 or later, you can use the
MongoClient.bulkWrite()method to perform bulk write operations on multiple collections and databases in the same cluster. This method performs all write operations in one database call.
コレクションの一括書込み (write)
一括書き込み操作には、1 つ以上の書き込み操作が含まれます。 コレクションレベルで一括書き込み操作を実行するには、WriteModel ドキュメントの Seq を MongoCollection.bulkWrite() メソッドに渡します。 WriteModel は 書込み操作を表すモデルです。
実行する書込み操作ごとに、WriteModel から継承する次のいずれかのクラスのインスタンスを作成します。
InsertOneModelUpdateOneModelUpdateManyModelReplaceOneModelDeleteOneModelDeleteManyModel
次に、これらのインスタンスのリストをbulkWrite()メソッドに渡します。
The following sections show how to create and use instances of the preceding classes. The Perform the Bulk Operation section demonstrates how to pass a list of models to the bulkWrite() method to perform the bulk operation.
サンプル データ
The examples in this section use the restaurants collection in the sample_restaurants database from the Atlas sample datasets. To access this collection from your Scala application, create a MongoClient that connects to an Atlas cluster and assign the following values to your database and collection variables:
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のインスタンスを作成し、次の引数を渡します。
コレクション内のドキュメントをマッチングするために使用される基準を指定するクエリフィルター。
Update operation that you want to perform. To learn more about update operations, see the Field Update Operators guide in the MongoDB Server manual.
次の例では、 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") )
いずれかの書き込み操作が失敗した場合、 Scalaドライバーは BulkWriteError を発生させ、それ以上の操作を実行しません。 BulkWriteError は、失敗した操作と例外に関する詳細を含む details アイテムを提供します。
注意
ドライバーが一括操作を実行する場合、ターゲット コレクションの書込み保証 (write concern) が使用されます。 ドライバーは、実行順序に関係なく、すべての操作を試行した後にすべての書込み保証 (write concern) エラーを報告します。
一括書き込みをカスタマイズする
オプションで、MongoCollection.bulkWrite() メソッドは BulkWriteOptions パラメータを受け入れます。このパラメータは、 一括書込み操作を構成するために使用できるオプションを指定します。オプションを指定しない場合、ドライバーはデフォルト設定で一括操作を実行します。書込み操作の動作を変更するには、クラスインスタンスをbulkWrite() メソッドの最後の引数として渡します。
次の表では、 BulkWriteOptionsインスタンスを構成するために使用できる setter メソッドについて説明します。
方式 | 説明 |
|---|---|
|
|
| Specifies whether the update operation bypasses document validation. This lets you update documents that don't meet the schema validation requirements, if any exist. For more information about schema validation, see Schema Validation in the MongoDB Server manual. |
| 操作に挟入するコメントを設定します。 |
| 操作のトップレベル変数を設定するためのパラメータ名と値のマップを提供します。値は、ドキュメント フィールドを参照しない定数または閉じた式である必要があります。 |
次のコードでは、オプションを作成し、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)