Docs Menu
Docs Home
/
MongoDB Manual
/ / /

bulkWrite

On this page

  • Definition
  • Syntax
  • Command Fields
  • Output
  • Behavior
  • Examples
  • Learn More
bulkWrite

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

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 at 0. You can use sharded collections.

The command takes the following fields:

Field
Type
Necessity
Description
insert
integer
Required
Namespace ID index for an insert operation, which must match a namespace ID index in the ns field in the nsInfo array. Indexes start at 0.
document
document
Required
Document to insert into the collection.
update
integer
Required
Namespace ID index for an update operation, which must match a namespace ID index in the ns field in the nsInfo array. Indexes start at 0.
filter
document
Optional
Query selector to limit the documents for the update or delete operation.
updateMods
document
Optional

Update operation to perform on the collection. You can specify one of these:

arrayFilters
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 arrayFilters.

multi
boolean
Optional

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.

Default is false.

hint
document
Optional
Index to use for the document filter. If the index doesn't exist, the update operation returns an error.
constants
document
Optional
Constants for an aggregation pipeline custom update.
collation
document
Optional
Collation for an update or delete operation.
delete
integer
Required
Namespace ID index for a delete operation, which must match a namespace ID index in the ns field in the nsInfo array. Indexes start at 0.
ns
string
Required
Namespace (database and collection) for the operations. Set the namespace ID index for each operation in ops to the matching namespace array index in ns. Indexes start at 0.
collectionUUID
string
Optional
UUID hexadecimal value that specifies the collection for the operations.
encryptionInformation
document
Optional
Encryption information schema and tokens for the operation. For details, see Encryption Schemas.
ordered
boolean
Optional

If true, perform ordered operations. Otherwise, perform unordered operations.

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 true.

bypassDocumentValidation
boolean
Optional

If true, the operation bypasses the document validation rules. If false, the documents must be valid.

Default is false.

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

let
document
Optional
Document with a list of constants to reference in the operation. For let examples, see Use Variables in let Option or c Field and Use Variables in let.
errorsOnly
boolean
Optional

If true, the operation only returns errors and omits other output.

Default is false.

cursor batchSize
integer
Optional
Cursor batch size for the bulkWrite command's returned results. For details, see cursor.batchSize().
writeConcern
string
Optional
Write concern for the operation. Omit to use the server default.

The command returns a document with these fields:

Field
Type
Description
cursor
document
Cursor with the command results.
cursor.id
integer
Cursor identifier.
cursor.firstBatch
document array
Results of the operations.
cursor.firstBatch.ok
integer
1 indicates the operation was successful. Otherwise, 0.
cursor.firstBatch.idx
integer
Operation index number, which corresponds to the operation in the ops array. The first operation has an idx value of 0.
cursor.firstBatch.code
integer
Code number for an error.
cursor.firstBatch.errmsg
string
Description for an error.
cursor.firstBatch.keyPattern
string
Document index key specification for an error.
cursor.firstBatch.keyValue
string
Document index key value for an error.
cursor.firstBatch.n
integer
Total number of documents affected by an operation.
cursor.firstBatch.nModified
integer
Number of documents modified by an update operation.
nErrors
integer
Number of errors for the bulkWrite command.
nInserted
integer
Number of inserted documents.
nMatched
integer
Number of matched documents.
nModified
integer
Number of modified documents.
nUpserted
integer
Number of upserted documents.
nDeleted
integer
Number of deleted documents.
ok
integer
1 indicates the bulkWrite command was successful. Otherwise, 0.

Note

The output fields may vary depending on the operations you run in the bulkWrite command.

This section describes the bulkWrite command behavior.

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.

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.

This section contains bulkWrite command examples.

The following bulkWrite example modifies a single namespace:

1

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 }
] )
2

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.

3

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.

You can specify multiple namespaces in a bulkWrite command.

The following bulkWrite example contains insert, update, and delete operations for two namespaces:

1

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 }
] )
2

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" ) }
] )
3

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.
]
} )
4

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
}

The following bulkWrite example contains operations with errors and operations that don't change any documents:

1

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 }
] )
2

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

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.

The following bulkWrite example sets errorsOnly to true to only show the error output:

1

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 }
] )
2

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

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
}

Back

autoCompact