Docs Menu

一括書き込み操作

このガイドでは、一括書込み操作を使用して、1 つのデータベース呼び出しで複数の書込み操作を実行する方法を学習できます。

ドキュメントを挿入し、複数の他のドキュメントを更新してから、ドキュメント を削除するシナリオを考えてみましょう。 個々のメソッドを使用する場合、各操作には独自のデータベース呼び出しが必要です。

一括書き込み操作 を使用すると、より少ないデータベース呼び出しで複数の書き込み操作を実行できます。 次のレベルで一括書き込み操作を実行できます。

  • コレクション :MongoCollection.bulkWrite() メソッドを使用して、単一のコレクションに対して一括書き込み操作を実行できます。このメソッドでは、それぞれの書き込み操作に少なくとも 1 回のデータベース呼び出しが必要です。 例、MongoCollection.bulkWrite() は 1 回の呼び出しで複数のアップデート操作を実行しますが、挿入操作と置換操作の場合はデータベースに 2 回個別の呼び出しを行います。

  • クライアント :アプリケーションがMongoDB Serverバージョン8.0 以降に接続している場合は、MongoClient.bulkWrite() メソッドを使用して、同じクラスター内の複数のコレクションとデータベースに対して一括書込み操作を実行できます。このメソッドは、1 回のデータベース呼び出しですべての書き込み操作を実行します。

このガイドの例では、sample_restaurants.restaurants sample_mflix.moviesAtlasサンプルデータセット の コレクションと コレクションを使用します。MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、 「Atlas を使い始める」ガイド を参照してください。

これらのコレクション内のドキュメントは、次のKotlinデータ クラスによってモデル化されます。

data class Restaurant(
val name: String,
val borough: String,
val cuisine: String
)
data class Movie(
val title: String,
val year: Int
)

一括書き込み操作には、1 つ以上の書き込み操作が含まれます。 コレクションレベルで一括書き込み操作を実行するには、WriteModel ドキュメントの ListMongoCollection.bulkWrite() メソッドに渡します。 WriteModel は 書込み操作を表すモデルです。

実行する書込み操作ごとに、WriteModel から継承する次のいずれかのクラスのインスタンスを作成します。

  • InsertOneModel

  • UpdateOneModel

  • UpdateManyModel

  • ReplaceOneModel

  • DeleteOneModel

  • DeleteManyModel

次のセクションでは、前述のクラスのインスタンスを作成して使用する方法を示します。 「一括操作の実行 」セクションでは、モデルのリストをbulkWrite()メソッドに渡して一括操作を実行する方法が説明されています。

挿入操作を実行するには、 InsertOneModelインスタンスを作成し、挿入するドキュメントを指定します。

次の例では、 InsertOneModelのインスタンスを作成しています。

val blueMoon = InsertOneModel(Restaurant("Blue Moon Grill", "Brooklyn", "American"))

複数のドキュメントを挿入するには、ドキュメントごとにInsertOneModelのインスタンスを作成します。

重要

一括操作 を実行する場合、InsertOneModel は、コレクションにすでに存在する _id 値を持つドキュメントの挿入を指示できません。 この状況では、ドライバーは MongoBulkWriteException をスローします。

ドキュメントを更新するには、 UpdateOneModelのインスタンスを作成し、次の引数を渡します。

  • コレクション内のドキュメントを照合するために使用される基準を指定するクエリフィルター

  • 実行する更新操作。 更新演算子の詳細については、 MongoDB Serverマニュアルの「 フィールド更新演算子」ガイドを参照してください。

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 メソッドについて説明します。

プロパティ
説明

ordered()

If true, the driver performs the write operations in the order provided. If an error occurs, the remaining operations are not attempted.

If false, the driver performs the operations in an arbitrary order and attempts to perform all operations.
Defaults to true.

bypassDocumentValidation()

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.
Defaults to false.

comment()

Sets a comment to attach to the operation.

let()

Provides a map of parameter names and values to set top-level variables for the operation. Values must be constant or closed expressions that don't reference document fields.

次のコードでは、オプションを作成し、 ordered(false)オプションを使用して順序なしの一括書き込みを指定します。 次に、この例ではbulkWrite()メソッドを使用して一括操作を実行します。

val opts = BulkWriteOptions().ordered(false)
collection.bulkWrite(bulkOperations, opts)

順序付けなし一括書き込み 内のいずれかの書き込み操作が失敗した場合、 Kotlin Sync ドライバーはすべての操作を試行した後にのみエラーを報告します。

注意

順序なしの一括操作では、実行順序は保証されません。 この順序は、ランタイムを最適化するために一覧表示する方法とは異なる場合があります。

bulkWrite()メソッドはBulkWriteResultオブジェクトを返します。 BulkWriteResultインスタンスから次の情報にアクセスできます。

プロパティ
説明

wasAcknowledged()

Indicates if the server acknowledged the write operation.

getDeletedCount()

The number of documents deleted, if any.

getInsertedCount()

The number of documents inserted, if any.

getInserts()

The list of inserted documents, if any.

getMatchedCount()

The number of documents matched for an update, if applicable.

getModifiedCount()

The number of documents modified, if any.

getUpserts()

The list of upserted documents, if any.

MongoDB Server 8.0 以降を実行中配置に接続する場合、MongoClient.bulkWrite() メソッドを使用して同じクラスター内の複数のデータベースとコレクションに書込み (write) できます。 MongoClient.bulkWrite() メソッドは、1 回の呼び出しですべての書き込み操作を実行します。

MongoClient.bulkWrite() メソッドは、さまざまな書込み操作を表すために ClientNamespacedWriteModel インスタンスのリストを受け取ります。 インスタンスメソッドを使用して、ClientNamespacedWriteModel インターフェースのインスタンスを構築できます。 例、ClientNamespacedInsertOneModel のインスタンスは1 つのドキュメントを挿入する操作を表します。このモデルは ClientNamespacedWriteModel.insertOne() メソッドを使用して作成できます。

モデルとそれに対応するインスタンスメソッドは、以下の表に説明されています。

モデル
インスタンス メソッド
説明
パラメーター

ClientNamespacedInsertOneModel

insertOne()

namespace にドキュメントを挿入するためのモデルを作成します。

namespace: 書き込み先のデータベースとコレクション

document: 挿入するドキュメント

ClientNamespacedUpdateOneModel

updateOne()

filter に一致する namespace 内の最初のドキュメントを更新するためのモデルを作成します。

namespace: 書き込み先のデータベースとコレクション

filter: 更新するドキュメントを選択するフィルター

update: 一致するドキュメントに適用するアップデート

updatePipeline: 一致するドキュメントに適用するパイプラインを更新

options:(任意)ドキュメント更新時に適用するオプション

update または updatePipeline パラメーターのいずれかに値を渡す必要があります。

ClientNamespacedUpdateManyModel

updateMany()

filter に一致する namespace 内のすべてのドキュメントを更新するモデルを作成します。

namespace: 書き込み先のデータベースとコレクション

filter: 更新するドキュメントを選択するフィルター

update: 一致するドキュメントに適用する更新

updatePipeline: 一致するドキュメントに適用するパイプラインを更新

options:(任意)ドキュメント更新時に適用するオプション

update または updatePipeline パラメーターのいずれかに値を渡す必要があります。

ClientNamespacedReplaceOneModel

replaceOne()

filter に一致する namespace 内の最初のドキュメントを置き換えるモデルを作成します。

namespace: 書き込み先のデータベースとコレクション

filter: 置き換えるドキュメントを選択するフィルター

replacement: 置換ドキュメント

options:(任意)ドキュメントの置き換え時に適用するオプション

ClientNamespacedDeleteOneModel

deleteOne()

filter に一致する namespace 内の最初のドキュメントを削除するためのモデルを作成します。

namespace: 書き込み先のデータベースとコレクション

filter: 削除するドキュメントを選択するフィルター

option:(任意)ドキュメントの削除時に適用するオプション

ClientNamespacedDeleteManyModel

deleteMany()

filter に一致する namespace 内のすべてのドキュメントを削除するモデルを作成します。

namespace: 書き込み先のデータベースとコレクション

filter: 削除するドキュメントを選択するフィルター

option:(任意)ドキュメントの削除時に適用するオプション

次のセクションでは、モデルを作成し、クライアントのbulkWrite() メソッドを使用する方法の例をいくつか示します。

この例では、 2 つのドキュメントを挿入する指示を含むモデルを作成する方法を示しています。 1 つのドキュメントはdb.peopleコレクションに挿入され、もう 1 つのドキュメントはdb.thingsコレクションに挿入されます。 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)
)

次の例は、 db.people コレクションと db.things コレクション内の既存のドキュメントを置き換えるためのモデルを作成する方法を示しています。

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)
)

この例が正常に実行されると、peopleコレクション内の _id 値が 1 であるドキュメントは、新しいドキュメントに置き換えられます。 _id 値が 1 である thingsコレクション内のドキュメントは、 新しいドキュメントに置き換えられます。

実行する操作ごとに 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インスタンスを作成するときに falseordered() メソッドに渡して、ドライバーに書込み操作を順序なしで実行させることができます。 順序付けなし オプションを使用する場合、エラーが発生しても操作はドライバーが 一括書込み操作で他の書込み操作を実行中ことを妨げるものではありません。

次のコードは、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 ドキュメントを参照してください。