2.1 Document Insertion Operations

Key Takeaways

  • The 'insertOne()' method inserts a single document returning an 'insertedId', while 'insertMany()' inserts an array of documents returning an 'insertedIds' map.
  • Bulk insertions execute as ordered writes ('ordered: true') by default, processing documents sequentially and halting immediately upon encountering the first error.
  • Setting '{ ordered: false }' executes unordered bulk inserts, attempting insertion of all documents regardless of individual write errors and aggregating failures into a BulkWriteError.
  • If a document is inserted without an '_id' field, MongoDB drivers automatically synthesize a unique 12-byte ObjectId before sending the payload over the wire.
  • Duplicate primary keys trigger an E11000 duplicate key error, which does not roll back previously completed inserts unless executed inside a multi-document ACID transaction.
Last updated: September 2026

Document Insertion Operations

In MongoDB, creating new records is the foundation of the CRUD (Create, Read, Update, Delete) lifecycle. Unlike relational database management systems that require explicit table declarations (CREATE TABLE) and column-oriented INSERT INTO statements, MongoDB provides dynamic, document-oriented insertion methods that create databases and collections implicitly upon the first write.

Understanding how write operations behave—specifically regarding primary key generation, return payloads, bulk operation ordering, and error containment—is a core domain on the MongoDB Associate Developer certification exam.


Core Insertion Methods: insertOne() and insertMany()

Modern MongoDB drivers and the MongoDB Shell (mongosh) provide two primary methods for inserting documents: db.collection.insertOne() and db.collection.insertMany(). Legacy methods such as db.collection.insert() and db.collection.save() are deprecated and should not be used in modern application development.

+-------------------------------------------------------------------------+
|                        MongoDB Insertion Methods                        |
|                                                                         |
|  +----------------------------------+  +-----------------------------+  |
|  |        insertOne(doc, opts)      |  |   insertMany([docs], opts)  |  |
|  |                                  |  |                             |  |
|  | Inserts a single BSON document.  |  | Inserts an array of BSON    |  |
|  | Returns:                         |  | documents in batches.       |  |
|  | - acknowledged: true/false       |  | Returns:                    |  |
|  | - insertedId: <_id value>        |  | - acknowledged: true/false  |  |
|  |                                  |  | - insertedIds: { '0': ... } |  |
|  +----------------------------------+  +-----------------------------+  |
+-------------------------------------------------------------------------+

1. Single Document Insertion: insertOne()

The insertOne() method adds exactly one BSON document to the target collection. If the collection does not already exist, MongoDB creates it automatically.

Syntax

db.collection.insertOne(
  <document>,
  {
    writeConcern: <document>
  }
)

Example: Registering a Customer Account

// In mongosh:
const insertResult = db.customers.insertOne({
  username: "jdoe_dev",
  email: "jdoe@example.com",
  tier: "Premium",
  loyalty_points: NumberInt(450),
  profile: {
    first_name: "John",
    last_name: "Doe",
    country: "USA"
  },
  created_at: new Date()
});

console.log(insertResult);

Return Document Structure

When an insertOne() operation succeeds, MongoDB returns a document containing two fields:

{
  "acknowledged": true,
  "insertedId": ObjectId("66d57a10f1e8a93b4c5d6e01")
}
  • acknowledged: A boolean indicating whether the write was acknowledged by the server according to the specified write concern (e.g., w: 1 or w: "majority").
  • insertedId: The value of the _id field for the inserted document. If the document lacked an _id, this contains the newly generated ObjectId.

2. Batch Document Insertion: insertMany()

The insertMany() method inserts an array of documents into a collection in an efficient batch operation over the network.

Syntax

db.collection.insertMany(
  [ <document 1>, <document 2>, ... ],
  {
    writeConcern: <document>,
    ordered: <boolean>
  }
)

Example: Batch Inserting Products

const batchResult = db.products.insertMany([
  {
    sku: "MUG-BLU-001",
    title: "Ceramic Coffee Mug - Blue",
    price: NumberDecimal("14.99"),
    in_stock: true
  },
  {
    sku: "MUG-RED-002",
    title: "Ceramic Coffee Mug - Red",
    price: NumberDecimal("14.99"),
    in_stock: true
  },
  {
    sku: "COASTER-SET-04",
    title: "Cork Coaster 4-Pack",
    price: NumberDecimal("9.50"),
    in_stock: false
  }
]);

console.log(batchResult);

Return Document Structure

{
  "acknowledged": true,
  "insertedIds": {
    "0": ObjectId("66d57a20f1e8a93b4c5d6e02"),
    "1": ObjectId("66d57a20f1e8a93b4c5d6e03"),
    "2": ObjectId("66d57a20f1e8a93b4c5d6e04")
  }
}
  • acknowledged: Confirms server acknowledgment.
  • insertedIds: A key-value map where each key is the zero-based integer index of the document in the input array, and the value is the corresponding _id assigned to that document.

The _id Primary Key & Automatic Generation

Every MongoDB document stored in a collection must possess a unique, immutable primary key in the top-level _id field. The database engine automatically builds a unique index on _id when the collection is initialized.

Automatic Client-Side Synthesis

If an application submits a document that lacks an _id field, the official MongoDB driver (or mongod if bypassing standard drivers) automatically generates a 12-byte BSON ObjectId and injects it into the document before transmitting the write payload across the network.

Application Document:      { name: "Alice", role: "Admin" }
                                   |
                                   v (Driver injects _id)
Wire Protocol Payload:     { _id: ObjectId("66d5..."), name: "Alice", role: "Admin" }

Custom _id Types

While ObjectId is the default, MongoDB allows developers to supply custom values for _id. Any BSON data type can serve as an _id, provided it is not an array:

// Valid custom _id types:
db.users.insertOne({ _id: "user_alpha_99", email: "alpha@test.com" });      // String
db.counters.insertOne({ _id: NumberLong(100452), counter_name: "hits" });   // 64-bit Integer
db.sensor_data.insertOne({
  _id: { device_id: "DEV-402", timestamp: ISODate("2026-09-02T10:00:00Z") }, // Embedded Subdocument
  reading: 24.8
});

// INVALID _id type (Throws MongoServerError: _id cannot be an array):
// db.inventory.insertOne({ _id: [1, 2, 3], item: "Invalid" });

Exam Trap: An _id field can be a String, Int32, Int64, Decimal128, UUID/Binary, or even an embedded Subdocument (commonly used as a compound natural primary key). However, an _id field cannot be an Array.

Immutability of _id

Once a document has been persisted to disk, its _id value is strictly immutable. If an application requires a document to have a different _id, the existing document must be deleted and re-inserted under the new identifier.


Ordered vs. Unordered Bulk Insertions

When executing insertMany(), developers can configure the execution strategy via the ordered boolean option. This setting fundamentally alters how MongoDB executes writes and handles runtime errors.

Operational AspectOrdered Inserts (ordered: true)Unordered Inserts (ordered: false)
Default BehaviorYes (Default if omitted)No (Must be explicitly specified)
Execution OrderStrictly serial (Document 0, then 1, then 2...)Non-deterministic / Arbitrary (Parallelized across shards)
Behavior on ErrorHalts immediately on the first failureContinues processing all remaining documents
Subsequent DocumentsNot processed; write operation abortsAll remaining valid documents are inserted
Previous DocumentsRemain in the database (No rollback)Remain in the database (No rollback)
Network & ShardingSequential batching to shard targetsHigh throughput; can be split and processed in parallel
Error PayloadSingle error report with index of failureBulkWriteError aggregating all write errors across array

Ordered Execution Mechanics (ordered: true)

In an ordered insert, MongoDB guarantees that documents are inserted in the exact sequence they appear in the array. If an error occurs (such as a duplicate key collision on document index 2), the operation immediately aborts.

Input Array: [ Doc 0 (Valid), Doc 1 (Valid), Doc 2 (Duplicate), Doc 3 (Valid), Doc 4 (Valid) ]
                   |
                   v
Step 1: Insert Doc 0 ---> SUCCESS
Step 2: Insert Doc 1 ---> SUCCESS
Step 3: Insert Doc 2 ---> ERROR (E11000 Duplicate Key)
                           |
                           +---> EXECUTION HALTS IMMEDIATELY
                                 Doc 3 and Doc 4 are NEVER processed!
// Executing an ordered insertMany:
try {
  db.inventory.insertMany([
    { _id: 101, item: "Notebook" },
    { _id: 102, item: "Pen" },
    { _id: 102, item: "Marker" },  // Duplicate _id 102!
    { _id: 103, item: "Eraser" },
    { _id: 104, item: "Ruler" }
  ], { ordered: true });
} catch (e) {
  console.error("Bulk write failed:", e.message);
}

// Result in database:
// Documents 101 and 102 (Notebook, Pen) ARE in the collection.
// Document 102 (Marker) failed.
// Documents 103 and 104 (Eraser, Ruler) WERE NEVER ATTEMPTED.

Unordered Execution Mechanics (ordered: false)

In an unordered insert, MongoDB makes no guarantees regarding insertion sequence. MongoDB optimizes throughput by reordering operations and distributing writes concurrently across shards or storage threads. If an error occurs on a specific document, MongoDB records the error and continues processing all remaining documents in the array.

Input Array: [ Doc 0 (Valid), Doc 1 (Valid), Doc 2 (Duplicate), Doc 3 (Valid), Doc 4 (Valid) ]
                   |
                   v (ordered: false)
Attempt Doc 0 ---> SUCCESS
Attempt Doc 1 ---> SUCCESS
Attempt Doc 2 ---> ERROR (E11000) [Recorded in BulkWriteError]
Attempt Doc 3 ---> SUCCESS
Attempt Doc 4 ---> SUCCESS
                   |
                   +---> ALL valid documents (0, 1, 3, 4) are persisted to disk!
// Executing an unordered insertMany:
try {
  db.inventory.insertMany([
    { _id: 201, item: "Monitor" },
    { _id: 202, item: "Keyboard" },
    { _id: 202, item: "Mouse" },     // Duplicate _id 202!
    { _id: 203, item: "Webcam" },
    { _id: 204, item: "Headset" }
  ], { ordered: false });
} catch (e) {
  console.log("Errors captured:", e.writeErrors.length);
  console.log("First error index:", e.writeErrors[0].index);
}

// Result in database:
// Documents 201, 202 (Keyboard), 203, and 204 ALL exist in the collection!
// Only the duplicate document (Mouse at index 2) failed.

Critical Exam Concept: Neither ordered nor unordered insertMany() performs a transactional rollback upon error. Documents successfully inserted prior to a failure (in ordered mode) or all valid documents across the batch (in unordered mode) remain permanently written in the collection unless executed inside an explicit multi-document ACID transaction (session.startTransaction()).


Duplicate Key Errors (E11000)

A Duplicate Key Error (Error Code 11000 / E11000) occurs whenever a write operation attempts to insert or update a document with a key value that already exists in an index marked with a unique constraint (including the default _id_ index).

Anatomy of an E11000 Error

MongoServerError: E11000 duplicate key error collection: store_db.inventory index: _id_ dup key: { _id: 102 }

When inspecting a BulkWriteError in application code:

try {
  db.users.insertMany(userBatch, { ordered: false });
} catch (err) {
  if (err.name === "BulkWriteError") {
    console.log(`Inserted ${err.result.nInserted} documents.`);
    err.writeErrors.forEach(we => {
      if (we.code === 11000) {
        console.error(`Duplicate key at array index ${we.index}: ${we.errmsg}`);
      } else {
        console.error(`Other error at array index ${we.index}: ${we.errmsg}`);
      }
    });
  }
}

Insert Methods Comparison Summary

FeatureinsertOne()insertMany() (Ordered)insertMany() (Unordered)
Input TypeSingle BSON objectArray of BSON objectsArray of BSON objects
Network Overhead1 round-trip per document1 batched round-trip1 batched round-trip
ThroughputLow (fine-grained)HighMaximum (parallelized)
On Duplicate ErrorThrows exception immediatelyHalts at error index; aborts restCollects error; inserts remainder
AtomicityAtomic at single-doc levelNot atomic as a whole batchNot atomic as a whole batch
Primary Use CaseReal-time user interactionsSequential workflowsBulk ETL data pipelines
Loading diagram...
Ordered vs Unordered Insert Execution Flow
Test Your Knowledge

An application executes db.collection.insertMany() with an array of five documents. Document index 2 contains a duplicate '_id' that causes an E11000 write error. If the operation is executed with '{ ordered: false }', which documents will exist in the collection after execution?

A
B
C
D
Test Your Knowledge

What is the structure of the return document when executing 'db.collection.insertMany()' successfully on a batch of three documents in the MongoDB Shell?

A
B
C
D
Test Your Knowledge

What happens when a developer calls 'db.collection.insertOne()' with a document that does not contain an '_id' field?

A
B
C
D
Test Your Knowledge

A developer executes 'db.orders.insertMany([docA, docB, docC, docD])' using default options. The collection already contains a document with the same '_id' as 'docC'. What is the resulting state of the database and execution flow?

A
B
C
D