Bulk Operations
On this page
Overview
In this guide, you can learn how to use bulk operations in the Kotlin driver.
To perform a single create, replace, update, or delete operation, you can use
the corresponding method. For example, to insert one document and replace one
document, you can use the insertOne()
and replaceOne()
methods. When you
use these methods, your client makes one call to the database for each operation.
By using a bulk write operation, you can perform multiple write operations in fewer database calls. You can perform bulk write operations at the following levels:
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.
Collection Bulk Write
Bulk write operations contain one or more write operations. To perform a bulk
write operation at the collection level, pass a List
of WriteModel
documents to the MongoCollection.bulkWrite()
method. A WriteModel
is a
model that represents a write operation.
The MongoCollection.bulkWrite()
method performs each kind of write
operation in a separate database call. For example, when you pass DeleteOneModel
,
DeleteManyModel
, and ReplaceOneModel
objects to the method, it performs
two calls: one for the delete operations and one for the replace operation.
Note
When the client splits operations into separate database calls, it might reorder operations for efficiency if the bulk write operation is not ordered. To learn more about operation execution order, see the Order of Execution section.
The following sections show how to create and use each WriteModel
document. 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 by the following Kotlin data class:
data class Person( 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:
Insert Operation
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.
Example
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.
Replace Operation
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.
Example
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)
If multiple documents match the query filter specified in
the ReplaceOneModel
instance, the operation replaces the first
result. You can specify a sort in a ReplaceOptions
instance to apply
an order to matched documents before the driver performs the replace
operation, as shown in the following code:
val opts = ReplaceOptions().sort(Sorts.ascending("_id"))
For more information about the methods and classes mentioned in this section, see the following resources:
ReplaceOneModel API documentation
ReplaceOptions API documentation
Unique indexes reference in the Server Manual
Update Operation
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.
Example
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)
If multiple documents match the query filter specified in
the UpdateOneModel
instance, the operation updates the first
result. You can specify a sort in an UpdateOptions
instance to apply
an order to matched documents before the driver performs the update
operation, as shown in the following code:
val opts = UpdateOptions().sort(Sorts.ascending("_id"))
For more information about the methods and classes mentioned in this section, see the following resources:
UpdateOneModel API documentation
UpdateManyModel API documentation
UpdateOptions API documentation
unique indexes Server Manual Explanation
Delete Operation
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.
Example
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:
Order of Execution
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.
Ordered Execution
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.
Example
The following example performs these bulk operations:
An insert operation for a document where the
name
is"Zaynab Omar"
and theage
is37
A replace operation for a document where the
_id
is1
with a new document that contains thelocation
fieldAn update operation for a document where the
_id
is6
to change thename
fieldA delete operation for all documents that have an
age
value greater than50
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 }
Unordered Execution
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:
Client Bulk Write
When connecting to a deployment running MongoDB server 8.0 or later,
you can use the MongoClient.bulkWrite()
method to write
to multiple databases and collections in the same cluster. The MongoClient.bulkWrite()
method performs all write operations in a single call.
The MongoClient.bulkWrite()
method takes a
list of ClientNamespacedWriteModel
instances to represent different write operations.
You can construct instances of the ClientNamespacedWriteModel
interface by using
instance methods. For example, an instance of ClientNamespacedInsertOneModel
represents an
operation to insert one document, and you can create this model by using
the ClientNamespacedWriteModel.insertOne()
method.
Note
Bulk Write Errors
If any of the write operations fail, the driver raises a
ClientBulkWriteException
and does not perform any further individual
operations. ClientBulkWriteException
includes a BulkWriteError
that can
be accessed by using the ClientBulkWriteException.getWriteErrors()
method, which provides details of the individual failure.
The models and their corresponding instance methods are described in the table below.
Model | Instance Method | Description | Parameters |
---|---|---|---|
|
| Creates a model to insert a document into the |
|
|
| Creates a model to update the first document in the |
You must pass a value for either the |
|
| Creates a model to update all documents in the |
You must pass a value for either the |
|
| Creates a model to replace the first document in the |
|
|
| Creates a model to delete the first document in the |
|
|
| Creates a model to delete all documents in the |
|
The following sections provide examples of how to use the client bulkWrite()
method. The sample data is modeled by the following Kotlin data classes:
data class Person( val id: Int, val name: String, ) data class Object( val id: Int, val type: String, )
To learn more about the methods and classes mentioned in this section, see the following API documentation:
Insert Operation
This example shows how to use the bulkWrite()
method to insert
two documents. One document is inserted into the sample_db.people
collection, while
the other document is inserted into the sample_db.objects
collection.
The MongoNamespace
instance defines the databases and collections that
each write operation applies to.
val docsToInsert = mutableListOf<ClientNamespacedWriteModel>() docsToInsert.add(ClientNamespacedWriteModel .insertOne( MongoNamespace("sample_db", "people"), Person(2, "Julia Smith") ) ) docsToInsert.add(ClientNamespacedWriteModel .insertOne( MongoNamespace("sample_db", "objects"), Object(2, "washing machine") ) ) val clientBulkResult = client.bulkWrite(docsToInsert)
Replace Operation
The following example shows how to use the bulkWrite()
method to replace
existing documents in the sample_db.people
and sample_db.things
collections.
val docsReplacements = mutableListOf<ClientNamespacedWriteModel>() docsReplacements.add(ClientNamespacedWriteModel .replaceOne( MongoNamespace("sample_db", "people"), Filters.eq(Person::id.name, 1), Person(1, "Frederic Hilbert") ) ) docsReplacements.add(ClientNamespacedWriteModel .replaceOne( MongoNamespace("sample_db", "objects"), Filters.eq(Object::id.name, 1), Object(1, "ironing board") ) ) val clientBulkResult = client.bulkWrite(docsReplacements)
After this example runs successfully, the document that has an _id
value of 1
in the people
collection is replaced with a new document. The document in
the things
collection that has an _id
value of 1
is replaced with a new document.
Bulk Write Options
You can pass an instance of ClientBulkWriteOptions
to the bulkWrite()
method to specify options when running the bulk write operations.
Order of Execution
By default, the individual operations in a bulk operation are executed in the
order that you specify them until an error occurs, or until they execute
successfully. However, you can pass false
to the ordered()
method on
the ClientBulkWriteOptions
interface to perform write operations in an
unordered way. When using the unordered option, an error-producing operation
does not prevent execution of other write operations in the call to the
bulkWrite()
method.
The following code sets the ordered()
method on an
instance of ClientBulkWriteOptions
and performs a bulk write operation to
insert multiple documents.
val namespace = MongoNamespace("sample_db", "people") val options = ClientBulkWriteOptions .clientBulkWriteOptions() .ordered(false) val bulkOperations = listOf( ClientNamespacedWriteModel.insertOne( namespace, Person(2, "Rudra Suraj") ), // Causes duplicate key error ClientNamespacedWriteModel.insertOne( namespace, Person(2, "Wendy Zhang") ), ClientNamespacedWriteModel.insertOne( namespace, Person(4, "Mario Bianchi") ) ) val result = client.bulkWrite(bulkOperations, options)
Even though the write operation inserting a document with a duplicate key results in an error, the other operations are executed because the write operation is unordered.
To learn more about the methods and classes mentioned in this section, see the following API documentation:
Summary
MongoCollection.bulkWrite()
To perform a bulk operation, you create and pass a list of
WriteModel
instances to the bulkWrite()
method.
There are 6 different WriteModel
subtypes: InsertOneModel
,
ReplaceOneModel
, UpdateOneModel
, UpdateManyModel
,
DeleteOneModel
and DeleteManyModel
.
There are two ways to execute the bulkWrite()
method:
Ordered, which performs the bulk operations in order until an error occurs, if any
Unordered, which performs all the bulk operations in any order and reports errors at the end, if any
To learn more about the collection bulkWrite
command, see the
db.collection.bulkWrite()
method reference in the MongoDB server Manual.
MongoClient.bulkWrite()
When connecting to a deployment running MongoDB server version 8.0 or later, you
can use the MongoClient.bulkWrite()
method to perform bulk operations on multiple
databases and collections at once.
To perform a client bulk operation, you create an pass a list of
ClientNamespacedWriteModel
instances to this method.
There are six subtypes of ClientNamespacedWriteModel
that are used to
represent write operations. To construct these write models, you can use the
corresponding ClientNamespacedWriteModel
methods insertOne()
, updateOne()
,
updateMany()
, replaceOne()
, deleteOne()
, and deleteMany()
. These
methods take a MongoNamespace
object that defines which
database and collection to write to.
The MongoClient.bulkWrite()
method can also take a ClientBulkWriteOptions
object to specify different options for how the command is executed.
To learn more about the client bulkWrite
command, see the
bulkWrite() method reference
in the MongoDB server Manual.