MongoDB Bulk Operations
Sending one command for every single change is slow when an application has thousands of changes to make. Each command travels over the network, waits for a reply, and returns. Bulk operations pack many changes into one request, which saves time and reduces network traffic.
The Delivery Truck Picture
Imagine moving boxes to a new house. Carrying one box per trip takes many trips. Loading the truck with fifty boxes and driving once finishes the job much sooner.
One by one Bulk
App --1 box--> DB (reply) App --[50 boxes in one trip]--> DB
App --1 box--> DB (reply) (one reply)
App --1 box--> DB (reply)
... 50 trips ... 1 tripinsertMany: Bulk Inserts
The insertMany method adds a list of documents in one call:
db.products.insertMany([
{ _id: 1, name: "Pen", price: 5 },
{ _id: 2, name: "Pencil", price: 3 },
{ _id: 3, name: "Notebook", price: 50 }
])MongoDB returns the ids of the inserted documents.
Ordered and Unordered Inserts
By default, insertMany runs in ordered mode. MongoDB inserts documents one after another and stops at the first error. Documents after the failed one never enter the collection.
The option ordered: false changes the behavior. MongoDB tries every document, skips the ones that fail, and reports the errors at the end:
db.products.insertMany(
[
{ _id: 4, name: "Eraser" },
{ _id: 1, name: "Duplicate Pen" },
{ _id: 5, name: "Ruler" }
],
{ ordered: false }
)The duplicate _id: 1 fails, while Eraser and Ruler still arrive in the collection.
Ordered: [ OK ] [ FAIL ] [ skipped ] stops at the first failure
Unordered: [ OK ] [ FAIL ] [ OK ] continues past the failureUnordered mode lets the server work on several parts at once, which often makes it faster.
bulkWrite: Mix Different Operations
The bulkWrite method combines inserts, updates, replacements, and deletes in a single request:
db.products.bulkWrite([
{ insertOne: { document: { _id: 10, name: "Marker", price: 20 } } },
{ updateOne: { filter: { _id: 1 }, update: { $set: { price: 6 } } } },
{ updateMany: { filter: { price: { $lt: 5 } }, update: { $inc: { price: 1 } } } },
{ deleteOne: { filter: { _id: 3 } } },
{ replaceOne: { filter: { _id: 2 }, replacement: { name: "Pencil HB", price: 4 } } }
])Supported Operation Types
| Operation | Job |
|---|---|
| insertOne | Adds one document |
| updateOne | Changes the first matching document |
| updateMany | Changes every matching document |
| replaceOne | Swaps the whole matching document |
| deleteOne | Removes the first matching document |
| deleteMany | Removes every matching document |
Read the Result
The command returns a summary of what happened:
{
insertedCount: 1,
matchedCount: 3,
modifiedCount: 3,
deletedCount: 1,
upsertedCount: 0
}Check these counts to confirm that the batch did what you expected. A matchedCount higher than modifiedCount means some documents already held the new values.
Bulk Upserts
A common task syncs data from another system. Each record either updates an existing document or creates a new one. Set upsert: true on each update operation:
db.products.bulkWrite([
{ updateOne: { filter: { sku: "A100" }, update: { $set: { price: 15 } }, upsert: true } },
{ updateOne: { filter: { sku: "A200" }, update: { $set: { price: 25 } }, upsert: true } }
])Ordered vs Unordered in bulkWrite
The same ordered option controls bulkWrite. Ordered mode keeps the sequence and stops at the first error, which matters when later steps depend on earlier ones. Unordered mode skips failed operations and keeps going, which suits independent changes.
- Choose ordered mode when an insert must exist before an update touches it.
- Choose unordered mode for large imports of unrelated records.
Batch Size
MongoDB limits the size of one message sent to the server. Drivers split very large lists into smaller batches automatically, so a single call can still handle many thousands of operations. Sending data in groups of about 1,000 documents keeps memory use steady and makes progress easy to track in logs.
for (let i = 0; i < allDocs.length; i += 1000) {
const batch = allDocs.slice(i, i + 1000);
db.products.insertMany(batch, { ordered: false });
}Error Handling
A failed bulk operation throws an error that lists each problem with its position in the batch. Read the error details, fix the bad records, and send only those records again. Wrap bulk calls in a try and catch block in application code so a single bad record does not crash the whole job.
Summary
Bulk operations reduce the number of trips between an application and MongoDB. The insertMany method handles large inserts, and bulkWrite mixes inserts, updates, replacements, and deletes in one request. Ordered mode stops at the first error, while unordered mode continues and reports every failure. Result counts confirm the outcome, and batches of moderate size keep large jobs steady.
