Fix This Page
Navigation

db.collection.bulkWrite()

Definition

db.collection.bulkWrite()

New in version 3.2.

Performs multiple write operations with controls for order of execution.

bulkWrite() has the following syntax:

db.collection.bulkWrite(
   [ <operation 1>, <operation 2>, ... ],
   {
      writeConcern : <document>,
      ordered : <boolean>
   }
)
Parameter Type Description
operations array

An array of bulkWrite() write operations.

Valid operations are:

See Write Operations for usage of each operation.

writeConcern document Optional. A document expressing the write concern. Omit to use the default write concern.
ordered boolean

Optional. A boolean specifying whether the mongod instance should perform an ordered or unordered operation execution. Defaults to true.

See Execution of Operations

Returns:
  • A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled.
  • A count for each write operation.
  • An array containing an _id for each successfully inserted or upserted documents.

Behavior

bulkWrite() takes an array of write operations and executes each of them. By default operations are executed in order. See Execution of Operations for controlling the order of write operation execution.

Write Operations

insertOne

Inserts a single document into the collection.

See db.collection.insertOne().

db.collection.bulkWrite( [
   { insertOne : { "document" : <document> } }
] )

updateOne and updateMany

Changed in version 3.4: Add support for collation. Refer to db.collection.updateOne() and db.collection.updateMany() for details

updateOne updates a single document in the collection that matches the filter. If multiple documents match, updateOne will update the first matching document only. See db.collection.updateOne().

db.collection.bulkWrite( [
   { updateOne :
      {
         "filter" : <document>,
         "update" : <document>,
         "upsert" : <boolean>
      }
   }
] )

updateMany updates all documents in the collection that match the filter. See db.collection.updateMany().

db.collection.bulkWrite( [
   { updateMany :
      {
         "filter" : <document>,
         "update" : <document>,
         "upsert" : <boolean>
      }
   }
] )

Use query selectors such as those used with find() for the filter field.

Use Update Operators such as $set, $unset, or $rename for the update field.

By default, upsert is false.

replaceOne

Changed in version 3.4: Add support for collation. Refer to db.collection.replaceOne() for details

replaceOne replaces a single document in the collection that matches the filter. If multiple documents match, replaceOne will replace the first matching document only. See db.collection.replaceOne().

db.collection.bulkWrite([
   { replaceOne :
      {
         "filter" : <document>,
         "replacement" : <document>,
         "upsert" : <boolean>
      }
   }
] )

Use query selectors such as those used with find() for the filter field.

The replacement field cannot contain update operators.

By default, upsert is false.

deleteOne and deleteMany

Changed in version 3.4: Add support for collation. Refer to db.collection.deleteOne() and db.collection.deleteMany() for details

deleteOne deletes a single document in the collection that match the filter. If multiple documents match, deleteOne will delete the first matching document only. See db.collection.deleteOne().

db.collection.bulkWrite([
   { deleteOne :  { "filter" : <document> } }
] )

deleteMany deletes all documents in the collection that match the filter. See db.collection.deleteMany().

db.collection.bulkWrite([
   { deleteMany :  { "filter" : <document> } }
] )

Use query selectors such as those used with find() for the filter field.

_id Field

If the document does not specify an _id field, then mongod adds the _id field and assign a unique ObjectId for the document before inserting or upserting it. Most drivers create an ObjectId and insert the _id field, but the mongod will create and populate the _id if the driver or application does not.

If the document contains an _id field, the _id value must be unique within the collection to avoid duplicate key error.

Update or replace operations cannot specify an _id value that differs from the original document.

Execution of Operations

The ordered parameter specifies whether bulkWrite() will execute operations in order or not. By default, operations are executed in order.

The following code represents a bulkWrite() with five operations.

db.collection.bulkWrite(
   [
      { insertOne : <document> },
      { updateOne : <document> },
      { updateMany : <document> },
      { replaceOne : <document> },
      { deleteOne : <document> },
      { deleteMany : <document> }
   ]
)

In the default ordered : true state, each operation will be executed in order, from the first operation insertOne to the last operation deleteMany.

If ordered is set to false, operations may be reordered by mongod to increase performance. Applications should not depend on order of operation execution.

The following code represents an unordered bulkWrite() with six operations:

db.collection.bulkWrite(
   [
      { insertOne : <document> },
      { updateOne : <document> },
      { updateMany : <document> },
      { replaceOne : <document> },
      { deleteOne : <document> },
      { deleteMany : <document> }
   ],
   { ordered : false }
)

With ordered : false, the results of the operation may vary. For example, the deleteOne or deleteMany may remove more or fewer documents depending on whether the run before or after the insertOne, updateOne, updateMany, or replaceOne operations.

Each group of operations can have at most 1000 operations. If a group exceeds this limit, MongoDB will divide the group into smaller groups of 1000 or less. For example, if the queue consists of 2000 operations, MongoDB creates 2 groups, each with 1000 operations.

The sizes and grouping mechanics are internal performance details and are subject to change in future versions.

Executing an ordered list of operations on a sharded collection will generally be slower than executing an unordered list since with an ordered list, each operation must wait for the previous operation to finish.

Capped Collections

bulkWrite() write operations have restrictions when used on a capped collection.

updateOne and updateMany throw a WriteError if the update criteria increases the size of the document being modified.

replaceOne throws a WriteError if the replacement document has a larger size than the original document.

deleteOne and deleteMany throw a WriteError if used on a capped collection.

Error Handling

bulkWrite() throws a BulkWriteError exception on errors.

Excluding Write Concern errors, ordered operations stop after an error, while unordered operations continue to process any remaining write operations in the queue.

Write concern errors are displayed in the writeConcernErrors field, while all other errors are displayed in the writeErrors field. If an error is encountered, the number of successful write operations are displayed instead of the inserted _id values. Ordered operations display the single error encountered while unordered operations display each error in an array.

Examples

Bulk Write Operations

The characters collection contains the following documents:

{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 },
{ "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 },
{ "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }

The following bulkWrite() performs multiple operations on the collection:

try {
   db.characters.bulkWrite(
      [
         { insertOne :
            {
               "document" :
               {
                  "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4
               }
            }
         },
         { insertOne :
            {
               "document" :
               {
                  "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3
               }
            }
         },
         { updateOne :
            {
               "filter" : { "char" : "Eldon" },
               "update" : { $set : { "status" : "Critical Injury" } }
            }
         },
         { deleteOne :
            { "filter" : { "char" : "Brisbane"} }
         },
         { replaceOne :
            {
               "filter" : { "char" : "Meldane" },
               "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 }
            }
         }
      ]
   );
}
catch (e) {
   print(e);
}

The operation returns the following:

{
   "acknowledged" : true,
   "deletedCount" : 1,
   "insertedCount" : 2,
   "matchedCount" : 2,
   "upsertedCount" : 0,
   "insertedIds" : {
      "0" : 4,
      "1" : 5
   },
   "upsertedIds" : {

   }
}

If the _id value for the second of the insertOne operations were a duplicate of an existing _id, the following exception would be thrown:

BulkWriteError({
   "writeErrors" : [
      {
         "index" : 0,
         "code" : 11000,
         "errmsg" : "E11000 duplicate key error collection: guidebook.characters index: _id_ dup key: { : 4 }",
         "op" : {
            "_id" : 5,
            "char" : "Taeln"
         }
      }
   ],
   "writeConcernErrors" : [ ],
   "nInserted" : 1,
   "nUpserted" : 0,
   "nMatched" : 0,
   "nModified" : 0,
   "nRemoved" : 0,
   "upserted" : [ ]
})

Since ordered was true by default, only the first operation completes successfully. The rest are not executed. Running the bulkWrite() with ordered : false would allow the remaining operations to complete despite the error.

Unordered Bulk Write

The characters collection contains the following documents:

{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 },
{ "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 },
{ "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }

The following bulkWrite() performs multiple unordered operations on the characters collection. Note that one of the insertOne stages has a duplicate _id value:

try {
   db.characters.bulkWrite(
         [
            { insertOne :
               {
                  "document" :
                  {
                     "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4
                  }
               }
            },
            { insertOne :
               {
                  "document" :
                     {
                        "_id" : 4, "char" : "Taeln", "class" : "fighter", "lvl" : 3
                     }
               }
            },
            { updateOne :
               {
                  "filter" : { "char" : "Eldon" },
                  "update" : { $set : { "status" : "Critical Injury" } }
               }
            },
            { deleteOne :
               { "filter" : { "char" : "Brisbane"} }
            },
            { replaceOne :
               {
                  "filter" : { "char" : "Meldane" },
                  "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 }
               }
            }
         ],
            { ordered : false }
      );
   }
   catch (e) {
   print(e);
}

The operation returns the following:

BulkWriteError({
   "writeErrors" : [
      {
         "index" : 0,
         "code" : 11000,
         "errmsg" : "E11000 duplicate key error collection: guidebook.characters index: _id_ dup key: { : 4 }",
         "op" : {
            "_id" : 4,
            "char" : "Taeln"
         }
      }
   ],
   "writeConcernErrors" : [ ],
   "nInserted" : 1,
   "nUpserted" : 0,
   "nMatched" : 2,
   "nModified" : 2,
   "nRemoved" : 1,
   "upserted" : [ ]
})

Since this was an unordered operation, the writes remaining in the queue were processed despite the exception.

Bulk Write with Write Concern

The enemies collection contains the following documents:

{ "_id" : 1, "char" : "goblin", "rating" : 1, "encounter" : 0.24 },
{ "_id" : 2, "char" : "hobgoblin", "rating" : 1.5, "encounter" : 0.30 },
{ "_id" : 3, "char" : "ogre", "rating" : 3, "encounter" : 0.2 },
{ "_id" : 4, "char" : "ogre berserker" , "rating" : 3.5, "encounter" : 0.12}

The following bulkWrite() performs multiple operations on the collection using a write concern value of "majority" and timeout value of 100 milliseconds:

try {
   db.enemies.bulkWrite(
      [
         { updateMany :
            {
               "filter" : { "rating" : { $gte : 3} },
               "update" : { $inc : { "encounter" : 0.1 } }
            },

         },
         { updateMany :
            {
               "filter" : { "rating" : { $lt : 2} },
               "update" : { $inc : { "encounter" : -0.25 } }
            },
         },
         { deleteMany : { "filter" : { "encounter" { $lt : 0 } } } },
         { insertOne :
            {
               "document" :
                  {
                     "_id" :5, "char" : "ogrekin" , "rating" : 2, "encounter" : 0.31
                  }
            }
         }
      ],
      { writeConcern : { w : "majority", wtimeout : 100 } }
   );
}
catch (e) {
   print(e);
}

If the total time required for all required nodes in the replica set to acknowledge the write operation is greater than wtimeout, the following writeConcernError is displayed when the wtimeout period has passed.

BulkWriteError({
   "writeErrors" : [ ],
   "writeConcernErrors" : [
      {
         "code" : 64,
         "errInfo" : {
            "wtimeout" : true
         },
         "errmsg" : "waiting for replication timed out"
      }
   ],
   "nInserted" : 1,
   "nUpserted" : 0,
   "nMatched" : 4,
   "nModified" : 4,
   "nRemoved" : 1,
   "upserted" : [ ]
   })

The result set shows the operations executed since writeConcernErrors errors are not an indicator that any write operations failed.