bulkWrite
Definition
New in version 8.0.
Starting in MongoDB 8.0, you can use the new bulkWrite
command to perform many insert, update, and delete operations on
multiple collections in one request. The existing
db.collection.bulkWrite()
method only allows you to modify one
collection in one request.
To specify each collection in the bulkWrite
command, use a
namespace (database and collection name).
Syntax
The command has this syntax:
db.adminCommand( { bulkWrite: 1, // Include the insert, update, and delete operations // in the ops array ops: [ { insert: <integer>, // Namespace ID index for insert operation. // Must match a namespace ID index in // ns specified later in the nsInfo array. document: <document> }, { update: <integer>, // Namespace ID index for update operation filter: <document>, updateMods: <document>, arrayFilters: [ <filterDocument0>, <filterDocument1>, ... ], multi: <bolean>, hint: <document>, constants: <document>, collation: <document> }, { delete: <integer>, // Namespace ID index for delete operation filter: <document>, multi: <boolean>, hint: <document>, collation: <document> }, ... // Additional insert, update, and delete operations in any order ... ], // Include the namespaces with collections to modify // in the nsInfo array. You can add multiple namespaces here. nsInfo: [ { ns: <string>, // Namespace (database and collection name) to modify. // Each operation namespace ID index // specified in the earlier ops array must // match a namespace ID index here. collectionUUID: <string>, encryptionInformation: <document> }, ... // Additional namespaces ... ], // Additional fields ordered: <boolean>, bypassDocumentValidation: <boolean>, comment: <string>, let: <document>, errorsOnly: <boolean>, cursor: { batchSize: <integer> }, writeConcern: <string> } )
In the command syntax, you can specify multiple:
Insert, update, and delete operations in any order in the
ops
array.Namespaces for the operations in the
nsInfo
array. To match the operation to the namespace, use the same namespace ID index. Indexes start at0
. You can use sharded collections.
Command Fields
The command takes the following fields:
Field | Type | Necessity | Description |
---|---|---|---|
| integer | Required | Namespace ID index for an insert operation, which must match a
namespace ID index in the |
| document | Required | Document to insert into the collection. |
| integer | Required | Namespace ID index for an update operation, which must match a
namespace ID index in the |
| document | Optional | Query selector to limit the documents for the update or delete operation. |
| document | Optional | Update operation to perform on the collection. You can specify one of these:
|
| document array | Optional | Array of filter documents that specify the documents to modify for an update operation on an array field. For details, see Array Update Operations with |
| boolean | Optional | If the Default is |
| document | Optional | Index to use for the document |
| document | Optional | Constants for an aggregation pipeline custom update. |
| document | Optional | Collation for an update or delete operation. |
| integer | Required | Namespace ID index for a delete operation, which must match a
namespace ID index in the |
| string | Required | Namespace (database and collection) for the operations. Set the
namespace ID index for each operation in |
| string | Optional | UUID hexadecimal value that specifies the collection for the operations. |
| document | Optional | Encryption information schema and tokens for the operation. For details, see Encryption Schemas. |
| boolean | Optional | If Ordered operations run in series. If an error occurs, any remaining operations are cancelled. Unordered operations run in parallel. If an error occurs, any remaining statements are run. The operations may be reordered by the server to increase performance. Therefore, your applications should not depend on the order of operation execution. Default is |
| boolean | Optional | If Default is |
| string | Optional | Optional. A user-provided comment to attach to this command. Once set, this comment appears alongside records of this command in the following locations:
A comment can be any valid BSON type (string, integer, object, array, etc). |
| document | Optional | Document with a list of constants to reference in the operation.
For |
| boolean | Optional | If Default is |
| integer | Optional | Cursor batch size for the |
| string | Optional | Write concern for the operation. Omit to use the server default. |
Output
The command returns a document with these fields:
Field | Type | Description |
---|---|---|
| document | Cursor with the command results. |
| integer | Cursor identifier. |
| document array | Results of the operations. |
| integer |
|
| integer | Operation index number, which corresponds to the operation in the
|
| integer | Code number for an error. |
| string | Description for an error. |
| string | Document index key specification for an error. |
| string | Document index key value for an error. |
| integer | Total number of documents affected by an operation. |
| integer | Number of documents modified by an update operation. |
| integer | Number of errors for the |
| integer | Number of inserted documents. |
| integer | Number of matched documents. |
| integer | Number of modified documents. |
| integer | Number of upserted documents. |
| integer | Number of deleted documents. |
| integer |
|
Note
The output fields may vary depending on the operations you run in the
bulkWrite
command.
Behavior
This section describes the bulkWrite
command behavior.
Multiple Document Field and Retryable Writes
If the multi
field is true
, the update or delete operation
updates or deletes all documents that match the document filter
. If
false
, the operation updates or deletes the first document that
matches the document filter
. For details on multi-document
transactions, see Transactions.
To enable retryable writes, see retryable writes.
You can use bulkWrite
insert operations with retryable writes and
the multi
field set to true
.
You can use bulkWrite
update and delete operations with the
multi
field set to true
. But, you cannot use update or delete
operations with both multi
set to true
and retryable writes.
Operation Performance
If you rewrite existing insert, update, and delete commands as a
bulkWrite
command and set errorsOnly
to true
, the
bulkWrite
command has similar performance as the existing commands.
If you set errorsOnly
to false
, performance is worse.
In addition, if you have a sequence of commands like this:
insert update delete
If you replace those commands with the following example fragment, then the command with the following fragment is faster regardless of other options:
{ bulkWrite: 0, ops: [ insert, update, delete ] }
Most of the performance improvement is because of network latency, which is variable depending on your implementation, but the example is always faster.
Examples
This section contains bulkWrite
command examples.
Single Namespace Bulk Write Example
The following bulkWrite
example modifies a single namespace:
Modify the pizzas example collection
Run the following bulkWrite
command to perform insert, update,
and delete operations on the pizzas
collection:
db.adminCommand( { bulkWrite: 1, // The ops array contains the insert, update, and delete // operations. ops: [ // Specify the namespace ID index immediately after // the insert, update, and delete text. // For example, "insert: 0" specifies the 0 namespace ID index, // which is the "test.pizzas" namespace in nsInfo at the end // of the example. // Insert a pizza. { insert: 0, document: { _id: 4, type: "sausage", size: "small", price: 12 } }, // Update the price for medium pizzas. { update: 0, filter: { size: "medium" }, updateMods: { $set: { price: 15 } } }, // Delete the pizza with an _id of 2. { delete: 0, filter: { _id: 2 } } ], // The nsInfo array contains the namespace to apply the // previous operations to. nsInfo: [ { ns: "test.pizzas" } // Namespace ID index is 0. ] } )
The pizzas
collection is in the default test
database, so
the ns
namespace is "test.pizzas"
. The namespace ID index
is 0
, which is set in the first field of the insert, update,
and delete operations in the ops
array.
Examine the output
The following bulkWrite
example output, with various ok: 1
fields and nErrors: 0
, indicates all operations were
successful:
{ cursor: { id: Long('0'), firstBatch: [ { ok: 1, idx: 0, n: 1 }, { ok: 1, idx: 1, n: 1, nModified: 1 }, { ok: 1, idx: 2, n: 1 } ], ns: 'admin.$cmd.bulkWrite' }, nErrors: 0, nInserted: 1, nMatched: 1, nModified: 1, nUpserted: 0, nDeleted: 1, ok: 1 }
For details about the output fields, see the earlier Output section.
Multiple Namespaces Bulk Write Example
You can specify multiple namespaces in a bulkWrite
command.
The following bulkWrite
example contains insert, update, and delete
operations for two namespaces:
Create the pizzas example collection
If you already have the pizzas
collection in your test
database, use the db.collection.drop()
method to drop it
first and then run:
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
Create the pizza orders example collection
Run:
db.pizzaOrders.insertMany( [ { _id: 0, type: "pepperoni", number: 5, orderDate: new Date( "2023-01-15T12:00:00Z" ) }, { _id: 1, type: "cheese", number: 15, orderDate: new Date( "2023-01-23T11:12:32Z" ) }, { _id: 2, type: "vegan", number: 20, orderDate: new Date( "2023-03-20T10:01:12Z" ) } ] )
Modify the example collections
Run the following bulkWrite
command to perform insert, update,
and delete operations on the example collections:
db.adminCommand( { bulkWrite: 1, // The ops array contains the insert, update, and delete // operations. ops: [ // Specify the namespace ID indexes immediately after // the insert, update, and delete. For example, "insert: 0" // specifies the 0 namespace ID index, which is the "test.pizzas" // namespace. And, "insert: 1" specifies "test.pizzaOrders". // Insert pizzas. // Namespace ID is 0 for "test.pizzas", which // is specified as "insert: 0". { insert: 0, document: { _id: 5, type: "sausage", size: "small", price: 12 } }, { insert: 0, document: { _id: 6, type: "vegan cheese", size: "large", price: 25 } }, // Update the price for cheese pizzas. { update: 0, filter: { type: "cheese" }, updateMods: { $set: { price: 15 } } }, // Delete pizzas with a price less than 7. { delete: 0, filter: { price: { $lt: 7 } } }, // Insert pizza orders. // Namespace ID is 1 for "test.pizzaOrders". { insert: 1, document: { _id: 3, type: "sausage", number: 7, orderDate: new Date( "2023-04-15T12:02:15Z" ) } }, { insert: 1, document: { _id: 4, type: "vegan", number: 16, orderDate: new Date( "2023-05-12T11:03:11Z" ) } }, // Update the number of pizza orders for cheese pizzas. { update: 1, filter: { type: "cheese" }, updateMods: { $set: { number: 50 } } }, // Delete the pizza order with an _id of 2. { delete: 1, filter: { _id: 2 } }, // Delete pizza orders placed before March 15, 2023. { delete: 1, filter: { orderDate: { $lte: ISODate( "2023-03-15T00:00:00Z" ) } } } ], // Namespaces nsInfo: [ { ns: "test.pizzas" }, // Namespace ID index is 0. { ns: "test.pizzaOrders" } // Namespace ID index is 1. ] } )
Examine the output
The following bulkWrite
example output indicates the
operations were successful:
{ cursor: { id: Long('0'), firstBatch: [ { ok: 1, idx: 0, n: 1 }, { ok: 1, idx: 1, n: 1 }, { ok: 1, idx: 2, n: 1, nModified: 1 }, { ok: 1, idx: 3, n: 1 }, { ok: 1, idx: 4, n: 1 }, { ok: 1, idx: 5, n: 1 }, { ok: 1, idx: 6, n: 1, nModified: 1 }, { ok: 1, idx: 7, n: 1 }, { ok: 1, idx: 8, n: 1 } ], ns: 'admin.$cmd.bulkWrite' }, nErrors: 0, nInserted: 4, nMatched: 2, nModified: 2, nUpserted: 0, nDeleted: 3, ok: 1 }
Operations with Errors Bulk Write Example
The following bulkWrite
example contains operations with errors and
operations that don't change any documents:
Create the pizzas example collection
If you already have the pizzas
collection in your test
database, use the db.collection.drop()
method to drop it
first and then run:
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
Attempt to modify the pizzas example collection
Run the following bulkWrite
command to perform insert, update,
and delete operations on the pizzas
collection:
db.adminCommand( { bulkWrite: 1, // The ops array contains the insert, update, and delete // operations. ops: [ // The namespace ID indexes are specified immediately after // the insert, update, and delete text. // For example, "insert: 0" specifies the 0 namespace ID index, // which is the "test.pizzas" namespace in nsInfo. // Attempt to add a duplicate document with an // _id of 1, which already exists and causes an error. { insert: 0, document: { _id: 1, type: "tomato", size: "small", price: 12 } }, // Attempt to add another duplicate document. { insert: 0, document: { _id: 2, type: "pepper", size: "small", price: 12 } }, // Attempt to change the price for extra large pizzas, // which don't exist. This doesn't cause an error but // doesn't update any documents. { update: 0, filter: { size: "extra large" }, updateMods: { $set: { price: 15 } } }, // Attempt to remove a document that doesn't exist. // This doesn't cause an error but doesn't delete any documents. { delete: 0, filter: { _id: 8 } } ], // The nsInfo array contains the namespace to apply the // previous operations to. nsInfo: [ { ns: "test.pizzas" } // Namespace ID index is 0. ], // Set the ordered field to false to run the remaining operations // after an operation returns an error. ordered: false } )
Examine the output
The following bulkWrite
example output shows the errors:
{ cursor: { id: Long("0"), firstBatch: [ { ok: 0, idx: 0, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 1 }', keyPattern: { _id: 1 }, keyValue: { _id: 1 }, n: 0 }, { ok: 0, idx: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 2 }', keyPattern: { _id: 1 }, keyValue: { _id: 2 }, n: 0 }, { ok: 1, idx: 2, n: 0, nModified: 0 }, { ok: 1, idx: 3, n: 0 } ], ns: 'admin.$cmd.bulkWrite' }, nErrors: 2, nInserted: 0, nMatched: 0, nModified: 0, nUpserted: 0, nDeleted: 0, ok: 1 }
For details about the output fields, including the error codes and messages, see the earlier Output section.
Bulk Write Example with errorsOnly Enabled
The following bulkWrite
example sets errorsOnly
to true
to
only show the error output:
Create the pizzas example collection
If you already have the pizzas
collection in your test
database, use the db.collection.drop()
method to drop it
first and then run:
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
Attempt to modify the pizzas example collection
Run the following bulkWrite
command to perform insert, update,
and delete operations on the pizzas
collection with
errorsOnly
set to true
:
db.adminCommand( { bulkWrite: 1, // The ops array contains the insert, update, and delete // operations. ops: [ // The namespace ID indexes are specified immediately after // the insert, update, and delete text. // For example, "insert: 0" specifies the 0 namespace ID index, // which is the "test.pizzas" namespace in nsInfo. // Attempt to add a duplicate document with an // _id of 1, which already exists and causes an error. { insert: 0, document: { _id: 1, type: "tomato", size: "small", price: 12 } }, // Attempt to add another duplicate document. { insert: 0, document: { _id: 2, type: "pepper", size: "small", price: 12 } }, // Attempt to change the price for extra large pizzas, // which don't exist. This doesn't cause an error but // doesn't update any documents. { update: 0, filter: { size: "extra large" }, updateMods: { $set: { price: 15 } } }, // Attempt to remove a document that doesn't exist. // This doesn't cause an error but doesn't delete any documents. { delete: 0, filter: { _id: 8 } } ], // The nsInfo array contains the namespace to apply the // previous operations to. nsInfo: [ { ns: "test.pizzas" } // Namespace ID index is 0. ], // Set the ordered field to false to run the remaining operations // after an operation returns an error. ordered: false, // Set the errorsOnly field to true to only output the errors. errorsOnly: true } )
Examine the output
The following bulkWrite
example output shows the errors:
{ cursor: { id: Long("0"), firstBatch: [ { ok: 0, idx: 0, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 1 }', keyPattern: { _id: 1 }, keyValue: { _id: 1 }, n: 0 }, { ok: 0, idx: 1, code: 11000, errmsg: 'E11000 duplicate key error collection: test.pizzas index: _id_ dup key: { _id: 2 }', keyPattern: { _id: 1 }, keyValue: { _id: 2 }, n: 0 }, ], ns: 'admin.$cmd.bulkWrite' }, nErrors: 2, nInserted: 0, nMatched: 0, nModified: 0, nUpserted: 0, nDeleted: 0, ok: 1 }