Overview
このガイドでは、一括書込み操作を使用して、1 つのデータベース呼び出しで複数の書込み操作を実行する方法を学習できます。
ドキュメントを挿入し、複数の他のドキュメントを更新してから、ドキュメント を削除するシナリオを考えてみましょう。 個々のメソッドを使用する場合、各操作には独自のデータベース呼び出しが必要です。
一括書き込み操作 を使用すると、より少ないデータベース呼び出しで複数の書き込み操作を実行できます。 次のレベルで一括書き込み操作を実行できます。
コレクション :
MongoCollection.bulkWrite()メソッドを使用して、単一のコレクションに対して一括書き込み操作を実行できます。このメソッドでは、それぞれの書き込み操作に少なくとも 1 回のデータベース呼び出しが必要です。 例、MongoCollection.bulkWrite()は 1 回の呼び出しで複数のアップデート操作を実行しますが、挿入操作と置換操作の場合はデータベースに 2 回個別の呼び出しを行います。クライアント :アプリケーションがMongoDB Serverバージョン8.0 以降に接続している場合は、
MongoClient.bulkWrite()メソッドを使用して、同じクラスター内の複数のコレクションとデータベースに対して一括書込み操作を実行できます。このメソッドは、1 回のデータベース呼び出しですべての書き込み操作を実行します。
サンプル データ
このガイドの例では、Atlasサンプルデータセットの sample_restaurants.restaurants コレクションと sample_mflix.movies コレクションを使用します。MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、Atlas を使い始める を参照してください。
これらのコレクション内のドキュメントは、次のKotlinデータ クラスによってモデル化されます。
data class Restaurant( val name: String, val borough: String, val cuisine: String, val stars: Int? = null, ) data class Movie( val title: String, val year: Int, val seen: Boolean? = null, )
コレクションの一括書込み (write)
一括書き込み操作には、1 つ以上の書き込み操作が含まれます。 コレクションレベルで一括書き込み操作を実行するには、WriteModel ドキュメントの List を MongoCollection.bulkWrite() メソッドに渡します。 WriteModel は 書込み操作を表すモデルです。
実行する書込み操作ごとに、WriteModel から継承する次のいずれかのクラスのインスタンスを作成します。
InsertOneModelUpdateOneModelUpdateManyModelReplaceOneModelDeleteOneModelDeleteManyModel
次のセクションでは、前述のクラスのインスタンスを作成して使用する方法を示します。 「一括操作の実行 」セクションでは、モデルのリストをbulkWrite()メソッドに渡して一括操作を実行する方法が説明されています。
挿入操作
挿入操作を実行するには、 InsertOneModelインスタンスを作成し、挿入するドキュメントを指定します。
次の例では、 InsertOneModelのインスタンスを作成しています。
val blueMoon = InsertOneModel(Restaurant("Blue Moon Grill", "Brooklyn", "American"))
複数のドキュメントを挿入するには、ドキュメントごとにInsertOneModelのインスタンスを作成します。
重要
一括操作 を実行する場合、InsertOneModel は、コレクションにすでに存在する _id 値を持つドキュメントの挿入を指示できません。 この状況では、ドライバーは MongoBulkWriteException をスローします。
アップデート操作
ドキュメントを更新するには、 UpdateOneModelのインスタンスを作成し、次の引数を渡します。
コレクション内のドキュメントを照合するために使用される基準を指定するクエリフィルター
UpdateOneModelインスタンスは、クエリフィルターに一致する最初のドキュメントの更新を指定します。
次の例では、 UpdateOneModelのインスタンスを作成しています。
val updateOneFilter = Filters.eq(Restaurant::name.name, "White Horse Tavern") val updateOneDoc = Updates.set(Restaurant::borough.name, "Queens") val tavernUpdate = UpdateOneModel<Restaurant>(updateOneFilter, updateOneDoc)
複数のドキュメントが UpdateOneModelインスタンスで指定されたクエリフィルターに一致する場合、この操作最初の結果が更新されます。次のコードに示すように、サーバーが更新操作を実行する前に、一致したドキュメントに順序を適用するために、UpdateOptionsインスタンスで並べ替えを指定できます。
val opts = UpdateOptions().sort(Sorts.ascending(Restaurant::name.name))
複数のドキュメントを更新するには、 UpdateManyModelのインスタンスを作成し、 UpdateOneModelと同じ引数を渡します。 UpdateManyModelクラスは、クエリフィルターに一致するすべてのドキュメントのアップデートを指定します。
次の例では、 UpdateManyModel のインスタンスを作成し、一致するドキュメントをすべてアップデートするようドライバーに指示します。
val updateManyFilter = Filters.eq(Restaurant::name.name, "Wendy's") val updateManyDoc = Updates.set(Restaurant::cuisine.name, "Fast food") val wendysUpdate = UpdateManyModel<Restaurant>(updateManyFilter, updateManyDoc)
置換操作
置換操作により、指定されたドキュメントのすべてのフィールドと値が削除され、指定した新しいフィールドと値に置き換えられます。 置換操作を実行するには、 ReplaceOneModelのインスタンスを作成し、クエリフィルターと、一致するドキュメントを置き換えるフィールドと値を渡します。
次の例では、 ReplaceOneModelのインスタンスを作成しています。
val replaceFilter = Filters.eq(Restaurant::name.name, "Cooper Town Diner") val replaceDoc = Restaurant("Smith Town Diner", "Brooklyn", "American") val replacement = ReplaceOneModel(replaceFilter, replaceDoc)
複数のドキュメントが ReplaceOneModelインスタンスで指定されたクエリフィルターに一致する場合、その操作は最初の結果を置き換えます。次のコードに示すように、サーバーが置換操作を実行する前に、一致したドキュメントに順序を適用するために、ReplaceOptionsインスタンスで並べ替えを指定できます。
val opts = ReplaceOptions().sort(Sorts.ascending(Restaurant::name.name))
Tip
複数のドキュメントの置換
複数のドキュメントを置き換えるには、ドキュメントごとにReplaceOneModelのインスタンスを作成します。
削除操作
ドキュメントを削除するには、 DeleteOneModelのインスタンスを作成し、削除するドキュメントを指定するクエリフィルターを渡します。 DeleteOneModelインスタンスには、クエリフィルターに一致する最初のドキュメントのみを削除するための手順が記載されています。
次の例では、 DeleteOneModelのインスタンスを作成しています。
val deleteOne = DeleteOneModel<Restaurant>(Filters.eq( Restaurant::name.name, "Morris Park Bake Shop" ))
複数のドキュメントを削除するには、 DeleteManyModelのインスタンスを作成し、削除するドキュメントを指定してクエリフィルターを渡します。 DeleteManyModelのインスタンスには、クエリフィルターに一致するすべてのドキュメントを削除するための手順が表示されます。
次の例では、 DeleteManyModelのインスタンスを作成しています。
val deleteMany = DeleteManyModel<Restaurant>(Filters.eq( Restaurant::cuisine.name, "Experimental" ))
一括操作の実行
実行する操作ごとにモデル インスタンスを定義した後、これらのインスタンスのリストをbulkWrite()メソッドに渡します。 デフォルトでは、 メソッドはモデルのリストで指定された順序で操作を実行します。
次の例では、 bulkWrite()メソッドを使用して複数の書込み操作を実行します。
val insertOneMdl = InsertOneModel(Restaurant("Red's Pizza", "Brooklyn", "Pizzeria")) val updateOneMdl = UpdateOneModel<Restaurant>( Filters.eq(Restaurant::name.name, "Moonlit Tavern"), Updates.set(Restaurant::borough.name, "Queens") ) val deleteManyMdl = DeleteManyModel<Restaurant>( Filters.eq(Restaurant::name.name, "Crepe") ) val bulkResult = collection.bulkWrite( listOf(insertOneMdl, updateOneMdl, deleteManyMdl) ) println(bulkResult)
AcknowledgedBulkWriteResult{insertedCount=1, matchedCount=5, removedCount=3, modifiedCount=2, upserts=[], inserts=[BulkWriteInsert{index=0, id=BsonObjectId{value=...}}]}
書き込み操作のいずれかが失敗した場合、 Kotlin Syncドライバーは BulkWriteError を発生させ、それ以上の操作を実行しません。 BulkWriteError は、失敗した操作を含む detailsフィールドを提供し、例外に関する詳細を示します。
注意
ドライバーが一括操作を実行する場合、ターゲット コレクションの書込み保証 (write concern) が使用されます。 ドライバーは、実行順序に関係なく、すべての操作を試行した後にすべての書込み保証 (write concern) エラーを報告します。
一括書き込み操作をカスタマイズする
オプションで、 bulkWrite()メソッドは、一括書き込み操作を構成するために使用できるオプションを指定する パラメーターを受け入れます。 オプションを指定しない場合、ドライバーはデフォルト設定で一括操作を実行します。
次の表では、 BulkWriteOptionsインスタンスを構成するために使用できる setter メソッドについて説明します。
プロパティ | 説明 |
|---|---|
|
|
| アップデート操作がドキュメント検証をバイパスするかどうかを指定します。これにより、スキーマ検証要件を満たさないドキュメントを更新することができます(存在する場合)。スキーマ検証の詳細については、 MongoDB Serverマニュアルの「 スキーマバリデーション 」を参照してください。デフォルトは |
| 操作に添付するコメントを設定します。 |
| 操作の最上位変数を設定するためのパラメーター名と値のマップを提供します。値は、ドキュメントフィールドを参照しない定数または閉じた式である必要があります。 |
次のコードでは、オプションを作成し、 ordered(false)オプションを使用して順序なしの一括書き込みを指定します。 次に、この例ではbulkWrite()メソッドを使用して一括操作を実行します。
val opts = BulkWriteOptions().ordered(false) collection.bulkWrite(bulkOperations, opts)
順序付けなし一括書き込み 内のいずれかの書き込み操作が失敗した場合、 Kotlin Sync ドライバーはすべての操作を試行した後にのみエラーを報告します。
注意
順序なしの一括操作では、実行順序は保証されません。 この順序は、ランタイムを最適化するために一覧表示する方法とは異なる場合があります。
戻り値
bulkWrite()メソッドはBulkWriteResultオブジェクトを返します。 BulkWriteResultインスタンスから次の情報にアクセスできます。
プロパティ | 説明 |
|---|---|
| サーバーが書込み (write) 操作を確認したかどうかを示します。 |
| 削除されたドキュメントの数(存在する場合)。 |
| 挿入されたドキュメントの数(存在する場合)。 |
| 挿入されたドキュメントのリスト(存在する場合)。 |
| アップデートに一致したドキュメントの数(該当する場合)。 |
| 変更されたドキュメントの数(存在する場合)。 |
| アップサートされたドキュメントの一覧(存在する場合)。 |
クライアント一括書込み (write)
MongoDB Server 8.0 以降を実行中配置に接続する場合、MongoClient.bulkWrite() メソッドを使用して同じクラスター内の複数のデータベースとコレクションに書込み (write) できます。 MongoClient.bulkWrite() メソッドは、1 回の呼び出しですべての書き込み操作を実行します。
MongoClient.bulkWrite() メソッドは、さまざまな書込み操作を表すために ClientNamespacedWriteModel インスタンスのリストを受け取ります。 インスタンスメソッドを使用して、ClientNamespacedWriteModel インターフェースのインスタンスを構築できます。 例、ClientNamespacedInsertOneModel のインスタンスは1 つのドキュメントを挿入する操作を表します。このモデルは ClientNamespacedWriteModel.insertOne() メソッドを使用して作成できます。
モデルとそれに対応するインスタンスメソッドは、以下の表に説明されています。
モデル | インスタンス メソッド | 説明 | パラメーター |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
次のセクションでは、モデルを作成し、クライアントのbulkWrite() メソッドを使用する方法の例をいくつか示します。
挿入操作
この例では、 2 つのドキュメントを挿入する指示を含むモデルを作成する方法を示しています。 1 つのドキュメントはsample_restaurants.restaurantsコレクションに挿入され、もう 1 つのドキュメントはsample_mflix.moviesコレクションに挿入されます。 MongoNamespaceインスタンスは、各書込み操作が適用されるターゲットデータベースとコレクションを定義します。
val restaurantToInsert = ClientNamespacedWriteModel .insertOne( MongoNamespace("sample_restaurants", "restaurants"), Restaurant("Blue Moon Grill", "Brooklyn", "American") ) val movieToInsert = ClientNamespacedWriteModel .insertOne( MongoNamespace("sample_mflix", "movies"), Movie("Silly Days", 2022) )
アップデート操作
次の例は、bulkWrite() メソッドを使用して、sample_restaurants.restaurants コレクションと sample_mflix.movies コレクション内の既存のドキュメントを更新する方法を示しています。
val restaurantUpdate = ClientNamespacedWriteModel .updateOne( MongoNamespace("sample_restaurants", "restaurants"), Filters.eq(Restaurant::name.name, "Villa Berulia"), Updates.inc(Restaurant::stars.name, 1) ) val movieUpdate = ClientNamespacedWriteModel .updateMany( MongoNamespace("sample_mflix", "movies"), Filters.eq(Movie::title.name, "Carrie"), Updates.set(Movie::seen.name, true) )
この例では、restaurantsコレクションで name 値が "Villa Berulia" であるドキュメントで、starsフィールドの値を 1 ずつ増加させます。また、moviesコレクション内で title 値が "Carrie" であるすべてのドキュメントの seenフィールドの値を true に設定します。
複数のドキュメントが ClientNamespacedUpdateOneModelインスタンスで指定されたクエリフィルターに一致する場合、この操作最初の結果が更新されます。次のコードに示すように、 ClientUpdateOneOptions インスタンスでソート順序を指定して、サーバーが更新操作を実行する前に一致したドキュメントに順序を適用できます。
val options = ClientUpdateOneOptions .clientUpdateOneOptions() .sort(Sorts.ascending("_id"))
置換操作
次の例は、 sample_restaurants.restaurants コレクションと sample_mflix.movies コレクション内の既存のドキュメントを置き換えるためのモデルを作成する方法を示しています。
val restaurantReplacement = ClientNamespacedWriteModel .replaceOne( MongoNamespace("sample_restaurants", "restaurants"), Filters.eq("_id", 1), Restaurant("Smith Town Diner", "Brooklyn", "American") ) val movieReplacement = ClientNamespacedWriteModel .replaceOne( MongoNamespace("sample_mflix", "movies"), Filters.eq("_id", 1), Movie("Loving Sylvie", 1999) )
この例が正常に実行されると、restaurantsコレクション内の _id 値が 1 であるドキュメントは、新しいドキュメントに置き換えられます。_id 値が 1 である moviesコレクション内のドキュメントも、新しいドキュメントに置き換えられます。
複数のドキュメントが ClientNamespacedReplaceOneModelインスタンスで指定されたクエリフィルターに一致する場合、その操作は最初の結果を置き換えます。次のコードに示すように、ClientReplaceOneOptionsインスタンスでソート順序を指定して、ドライバーが置換操作を実行する前に一致したドキュメントに順序を適用できます。
val options = ClientReplaceOneOptions .clientReplaceOneOptions() .sort(Sorts.ascending("_id"))
一括操作の実行
実行する操作ごとに ClientNamespacedWriteModelインスタンスを定義した後、これらのインスタンスのリストをクライアントの bulkWrite() メソッドに渡します。 デフォルトでは 、メソッドは指定された順序で操作を実行します。
次の例では、 bulkWrite()メソッドを使用して複数の書込み操作を実行します。
val restaurantNamespace = MongoNamespace("sample_restaurants", "restaurants") val movieNamespace = MongoNamespace("sample_mflix", "movies") val bulkOperations = listOf( ClientNamespacedWriteModel .insertOne( restaurantNamespace, Restaurant("Drea's", "Brooklyn", "Mexican") ), ClientNamespacedWriteModel .replaceOne( movieNamespace, Filters.eq("_id", 1), Movie("Underneath It All", 2002) ) ) val clientBulkResult = mongoClient .bulkWrite(bulkOperations) println(clientBulkResult.toString())
AcknowledgedSummaryClientBulkWriteResult{insertedCount=1, matchedCount=1, ...}
書き込み操作のいずれかが失敗した場合、ドライバーは ClientBulkWriteException を発生させ、それ以上の個々の操作を実行しません。 ClientBulkWriteException には ClientBulkWriteException.getWriteErrors() メソッドを使用してアクセスできる BulkWriteError が含まれており、個々の障害の詳細が提供されます。
一括書き込みをカスタマイズする
ClientBulkWriteOptions のインスタンスをbulkWrite() メソッドに渡して、ドライバーが 一括書込み操作を実行する方法をカスタマイズできます。
実行順序
デフォルトでは 、ドライバーは、エラーが発生するまで、または操作が正常に完了するまで、指定された順序で個々の操作を一括操作で実行します。
ただし、ClientBulkWriteOptionsインスタンスを作成するときに false を ordered() メソッドに渡して、ドライバーに書込み操作を順序なしで実行させることができます。 順序付けなし オプションを使用する場合、エラーが発生しても操作はドライバーが 一括書込み操作で他の書込み操作を実行中ことを妨げるものではありません。
次のコードは、ClientBulkWriteOptions のインスタンスで ordered オプションを false に設定し、一括書き込み操作を実行して複数のドキュメントを挿入します。
val namespace = MongoNamespace("sample_restaurants", "restaurants") val options = ClientBulkWriteOptions .clientBulkWriteOptions() .ordered(false) val bulkOps = listOf( ClientNamespacedWriteModel.insertOne( namespace, Document("_id", 1).append("name", "Freezyland") ), // Causes a duplicate key error ClientNamespacedWriteModel.insertOne( namespace, Document("_id", 1).append("name", "Coffee Stand No. 1") ), ClientNamespacedWriteModel.insertOne<Any>( namespace, Document("name", "Kelly's Krepes") ) ) val result = mongoClient .bulkWrite(bulkOps, options)
重複キーを持つドキュメントを挿入する書込み操作ではエラーが発生しますが、書込み操作は順序付けがないため、他の操作が実行されます。
詳細情報
個々の書込み操作を実行する方法については、次のガイドを参照してください。
API ドキュメント
このガイドで説明したメソッドや型の詳細については、次の API ドキュメントを参照してください。
クライアント一括書込み (write)