Docs Menu
Docs Home
/ / /
Kotlin Coroutine
/ / /

Bulk Operations

On this page

  • Overview
  • Performing Bulk Operations
  • Insert Operation
  • Replace Operation
  • Update Operation
  • Delete Operation
  • Order of Execution
  • Ordered Execution
  • Unordered Execution
  • Summary

In this guide, you can learn how to use bulk operations in the MongoDB Kotlin Driver.

For individual CRUD operations, you can use the relevant method. For example, to insert one document and then update multiple documents, you can use the insertOne() method and the updateMany() method.

The MongoClient performs these operations by making a request to the database corresponding to each operation. You can reduce the number of calls to the database by using bulk operations.

Bulk operations consist of a large number of write operations. To perform a bulk operation, pass a List containing WriteModel documents to the bulkWrite() method. A WriteModel is a model that represents a single write operation.

The following sections show how to create and use each variation of the WriteModel type. The examples in each section use the following documents in the people collection:

{ "_id": 1, "name": "Karen Sandoval", "age": 31 }
{ "_id": 2, "name": "William Chin", "age": 54 }
{ "_id": 8, "name": "Shayla Ray", "age": 20 }

This data is modeled with the following Kotlin data class:

data class Person(
@BsonId val id: Int,
val name: String,
val age: Int? = null,
val location: String? = null
)

For more information about the methods and classes mentioned in this section, see the following API Documentation:

  • bulkWrite()

  • WriteModel

  • BulkWriteOptions

To perform an insert operation, create an InsertOneModel specifying the document you want to insert. To insert multiple documents, you must create an InsertOneModel for each document you want to insert.

The following example creates an InsertOneModel for two documents describing people:

val juneDoc = InsertOneModel(Person(3, "June Carrie", 17))
val kevinDoc = InsertOneModel(Person(4, "Kevin Moss", 22))

Important

When performing a bulkWrite() operation, the InsertOneModel cannot insert a document with an _id that already exists in the collection. In this case, the driver throws a MongoBulkWriteException.

The following example tries to insert two documents where the _id values are 1 and 3. Since there is already a document with an _id of 1 in the collection, the operation results in an error:

try {
val bulkOperations = listOf(
(InsertOneModel(Person(1, "James Smith", 13))),
(InsertOneModel(Person(3, "Colin Samuels")))
)
val bulkWrite = collection.bulkWrite(bulkOperations)
} catch (e: MongoBulkWriteException) {
println("A MongoBulkWriteException occurred with the following message: " + e.message)
}
A MongoBulkWriteException occurred with the following message:
Bulk write operation error on server sample-shard-00-02.pw0q4.mongodb.net:27017.
Write errors: [BulkWriteError{index=0, code=11000, message='E11000 duplicate key
error collection: crudOps.bulkWrite index: _id_ dup key: { _id: 1 }', details={}}].

To learn about why the driver didn't insert the document with the _id of 3, see the Order of Execution section.

For more information about the methods and classes mentioned in this section, see the InsertOneModel API Documentation.

To perform a replace operation, create a ReplaceOneModel specifying a query filter for the document you want to replace and the replacement document.

Important

When performing a bulkWrite(), the ReplaceOneModel cannot make changes that violate unique index constraints on the collection. Additionally, the model does not perform the replace operation if there are no matches to the query filter.

The following example creates a ReplaceOneModel to replace a document where the _id is 1 with a document that contains the additional location field:

val filter = Filters.eq("_id", 1)
val insert = Person(1, "Celine Stork", location = "San Diego, CA")
val doc = ReplaceOneModel(filter, insert)

For more information about the methods and classes mentioned in this section, see the following resources:

To perform an update operation, create an UpdateOneModel or an UpdateManyModel that specifies a query filter and an update document.

The UpdateOneModel updates the first document that matches your query filter and the UpdateManyModel updates all the documents that match your query filter.

Important

When performing a bulkWrite(), the UpdateOneModel and UpdateManyModel types cannot make changes that violate unique index constraints on the collection. Additionally, the models do not perform update operations if there are no matches to the query filter.

The following example creates an UpdateOneModel to increment the age field by 1 in a document where the _id is 2:

val filter = Filters.eq("_id", 2)
val update = Updates.inc(Person::age.name, 1)
val doc = UpdateOneModel<Person>(filter, update)

For more information about the methods and classes mentioned in this section, see the following resources:

To perform a delete operation, create a DeleteOneModel or a DeleteManyModel that specifies a query filter for documents you want to delete.

The DeleteOneModel deletes the first document that matches your query filter and the DeleteManyModel deletes all the documents that match your query filter.

Important

When performing a bulkWrite(), the DeleteOneModel and DeleteManyModel types do not delete any documents if there are no matches to the query filter.

The following example creates a DeleteOneModel to delete a document where the _id is 1 and a DeleteManyModel to delete documents where the age value is less than 30:

val deleteId1 = DeleteOneModel<Person>(Filters.eq("_id", 1))
val deleteAgeLt30 = DeleteManyModel<Person>(Filters.lt(Person::age.name, 30))

For more information about the methods and classes mentioned in this section, see the following API Documentation:

The bulkWrite() method accepts an optional BulkWriteOptions as a second parameter to specify if you want to execute the bulk operations as ordered or unordered.

By default, the bulkWrite() method executes bulk operations in order. This means that the operations execute in the order you added them to the list until any error occurs.

The following example performs these bulk operations:

  • An insert operation for a document where the name is "Zaynab Omar" and the age is 37

  • A replace operation for a document where the _id is 1 with a new document that contains the location field

  • An update operation for a document where the _id is 6 to change the name field

  • A delete operation for all documents that have an age value greater than 50

val insertMdl = InsertOneModel(Person(6, "Zaynab Omar", 37))
val replaceMdl = ReplaceOneModel(
Filters.eq("_id", 1),
Person(1, "Sandy Kane", location = "Helena, MT")
)
val updateMdl = UpdateOneModel<Person>(
Filters.eq("_id", 6),
Updates.set(Person::name.name, "Zaynab Hassan")
)
val deleteMdl = DeleteManyModel<Person>(Filters.gt(Person::age.name, 50))
val bulkOperations = listOf(
insertMdl,
replaceMdl,
updateMdl,
deleteMdl
)
val result = collection.bulkWrite(bulkOperations)

After running this example, your collection contains the following document:

{ "_id": 1, "name": "Sandy Kane", "location": "Helena, MT" }
{ "_id": 8, "name": "Shayla Ray", "age": 20 }
{ "_id": 6, "name": "Zaynab Hassan", "age": 37 }

You can also execute bulk operations in any order by passing false to the ordered() method on a BulkWriteOptions object. This means that all the write operations execute regardless of errors. If any errors occur, the driver reports them at the end.

The following code shows how to execute a bulk operation with no order of execution:

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

Note

Unordered bulk operations do not guarantee the order of execution. The order may differ from the way you list them to optimize the runtime.

In the preceding example, if the bulkWrite() method performed the insert operation after the update operation, the update operation would not produce changes because the document did not exist at that point in time. The collection would then contain the following documents:

{ "_id": 1, "name": "Sandy Kane", "location": "Helena, MT" }
{ "_id": 8, "name": "Shayla Ray", "age": 20 }
{ "_id": 6, "name": "Zaynab Omar", "age": 37 }

For more information about the methods and classes mentioned in this section, see the following API Documentation:

To perform a bulk operation, create and pass a list of WriteModel documents to the bulkWrite() method.

There are six variations of WriteModel:

  • InsertOneModel

  • ReplaceOneModel

  • UpdateOneModel

  • UpdateManyModel

  • DeleteOneModel

  • DeleteManyModel

There are two ways to execute the bulkWrite() method:

  • Ordered, where the driver performs the write operations in order until any error occurs

  • Unordered, where the driver performs all the write operations in any order and reports any errors after the operations complete

Back

Insert or Update in a Single Operation