Inserting data, bulk writes & write concern

This section documents the current MongoDB 8.x server line as published at the MongoDB Server Manual, which is the reference these pages are written and verified against. No specific patch version is pinned. Some capabilities (Atlas Search, Atlas Vector Search, and parts of encryption and backup) are Atlas-only — they are linked, not documented in depth.

This content was generated with the assistance of AI and should be verified against the official manual before being relied on in production, since MongoDB iterates quickly.

This section’s bibliography lists the reference material consulted while preparing these pages.

This page covers getting documents into a collection: the insertOne / insertMany / bulkWrite methods, the result objects they return, and the write concern that decides how many nodes must acknowledge a write before the driver considers it done. For updating and removing documents see Updating & deleting; for reads see Querying.

insertOne and insertMany

insertOne writes a single document; insertMany writes an array of documents in one round trip. If a document has no _id field, the driver adds one — an ObjectId by default — before sending it.

// https://www.mongodb.com/docs/manual/tutorial/insert-documents/
db.products.insertOne({ name: "Widget", price: 9.99 })

db.products.insertMany([
  { name: "Cog",    price: 2.50 },
  { name: "Sprong", price: 4.00 }
])

The result reports whether the write was acknowledged and the _id values that were stored (generated ones included):

// insertOne
{ "acknowledged": true, "insertedId": ObjectId("665f1a2b9c4d5e6f7a8b9c0d") }

// insertMany
{
  "acknowledged": true,
  "insertedIds": {
    "0": ObjectId("665f1a2b9c4d5e6f7a8b9c0e"),
    "1": ObjectId("665f1a2b9c4d5e6f7a8b9c0f")
  }
}

Ordered vs. unordered

By default insertMany is ordered: the server inserts documents in array order and stops at the first error, leaving the remaining documents un-inserted. Passing { ordered: false } makes it unordered: the server attempts every document, skipping only the ones that fail, and reports all errors together.

// second document duplicates an existing _id
db.products.insertMany(
  [ { _id: 10, name: "A" }, { _id: 10, name: "B" }, { _id: 11, name: "C" } ],
  { ordered: false }
)
// ordered:false -> _id 10 (first) and 11 inserted, the duplicate is reported in writeErrors
// ordered:true  -> only _id 10 (first) inserted, then execution halts

bulkWrite

bulkWrite sends a mixed batch of insertOne, updateOne, updateMany, deleteOne, deleteMany and replaceOne operations in one call. It also honours ordered (default true) vs. { ordered: false }, with the same stop-on-first-error vs. attempt-all semantics as insertMany.

// https://www.mongodb.com/docs/manual/core/bulk-write-operations/
db.inventory.bulkWrite([
  { insertOne:  { document: { _id: "sku-1", qty: 100 } } },
  { updateOne:  { filter: { _id: "sku-2" }, update: { $inc: { qty: -3 } } } },
  { replaceOne: { filter: { _id: "sku-3" }, replacement: { _id: "sku-3", qty: 0 } } },
  { deleteOne:  { filter: { _id: "sku-4" } } }
], { ordered: false })

The result tallies each operation kind and lists any generated ids:

{
  "acknowledged": true,
  "insertedCount": 1,
  "matchedCount": 2,
  "modifiedCount": 1,
  "deletedCount": 1,
  "upsertedCount": 0,
  "insertedIds": { "0": "sku-1" },
  "upsertedIds": {}
}

The update, replace and delete operations above are described in Updating & deleting.

Write concern

Write concern is the level of acknowledgement requested from the deployment. It is expressed as a document { w, j, wtimeout }:

  • w — how many members must acknowledge. w: 1 means the primary alone; w: "majority" means a majority of voting members, so the write survives a failover. A number greater than 1 names an explicit count.

  • j — if true, each acknowledging member must have written the operation to its on-disk journal, not merely to memory.

  • wtimeout — a millisecond cap on how long to wait for the w acknowledgements; on expiry the client gets a timeout error, though the write may still have been applied.

The server default write concern is { w: "majority" } for most deployments; it can be inspected and changed with getDefaultRWConcern / setDefaultRWConcern. Write concern can be set per operation, or per connection via the connection string (?w=majority&journal=true).

// https://www.mongodb.com/docs/manual/reference/write-concern/
db.orders.insertOne(
  { _id: 7, total: 42 },
  { writeConcern: { w: "majority", j: true, wtimeout: 5000 } }
)

// per-connection default in the URI:
// mongodb://host1,host2,host3/shop?replicaSet=rs0&w=majority&journal=true

A "majority" acknowledgement is tied to the replica set’s oplog and majority-commit point; see Replication for how the oplog and majority reads and writes fit together.

The w: "majority" acknowledgement path

sequenceDiagram participant C as Client / driver participant P as Primary participant O as Primary oplog participant S1 as Secondary 1 participant S2 as Secondary 2 C->>P: insert { writeConcern: { w: "majority" } } P->>O: append oplog entry, apply locally O-->>S1: replicate oplog entry O-->>S2: replicate oplog entry S1-->>P: replicated (ack) S2-->>P: replicated (ack) Note over P: majority (2 of 3) reached P-->>C: write acknowledged

Retryable writes

With retryable writes enabled (the driver default; retryWrites=true in the connection string), the driver automatically retries a write once if it fails due to a transient network error or a primary election. The server deduplicates the retry using the operation’s statement id and the session’s transaction number, so a single-document insertOne, updateOne, deleteOne, findAndModify or replaceOne is applied at most once even though it was sent twice.

// https://www.mongodb.com/docs/manual/core/retryable-writes/
// mongodb://host1,host2,host3/shop?replicaSet=rs0&retryWrites=true
db.accounts.updateOne({ _id: "a-1" }, { $inc: { balance: -100 } })
// if the primary steps down mid-write, the driver retries once against the new primary;
// the $inc is not applied twice

Multi-document operations that are not inherently idempotent (updateMany, deleteMany) are not retried. Wrapping several writes in a transaction (see Transactions) gives all-or-nothing semantics across documents.