MongoDBInsert Documents

Insert Documents

MongoDB provides three methods for inserting documents into a collection: insertOne(), insertMany(), and the legacy insert(). The insertOne() and insertMany() methods were introduced in MongoDB 3.2 and are the recommended approach for all new code. The older insert() method is deprecated and should not be used.

If the target collection does not exist when you call an insert method, MongoDB creates it automatically before inserting.

insertOne()

insertOne() inserts a single document into a collection. It returns an InsertOneResult object containing:

  • acknowledgedtrue if the write was acknowledged by the server.
  • insertedId — the _id of the inserted document (auto-generated ObjectId if you did not provide one).

insertOne() example

JS
// Insert a single user document
const result = db.users.insertOne({
  name:      "Alice",
  email:     "alice@example.com",
  age:       28,
  role:      "admin",
  active:    true,
  createdAt: new Date()
})

// MongoDB auto-generates _id when you don't provide one
console.log(result.insertedId)   // ObjectId("64f1a2b3...")

insertOne() result

JS
{
  acknowledged: true,
  insertedId: ObjectId("64f1a2b3c4d5e6f7a8b9c0d1")
}
insertMany()

insertMany() inserts an array of documents in a single operation. It returns an InsertManyResult with:

  • acknowledgedtrue if the write was acknowledged.
  • insertedIds — a map of array index → _id for each inserted document.

Sending multiple documents in one insertMany() call is significantly more efficient than looping with insertOne() because the documents are batched into fewer network round-trips.

insertMany() example

JS
const result = db.products.insertMany([
  {
    sku:      "WIDGET-42",
    name:     "Blue Widget",
    price:    9.99,
    stock:    500,
    category: "widgets",
    tags:     ["sale", "popular"],
    createdAt: new Date()
  },
  {
    sku:      "GADGET-7",
    name:     "Red Gadget",
    price:    24.50,
    stock:    120,
    category: "gadgets",
    tags:     ["new"],
    createdAt: new Date()
  },
  {
    sku:      "DOOHICKEY-1",
    name:     "Purple Doohickey",
    price:    4.99,
    stock:    1_000,
    category: "accessories",
    tags:     [],
    createdAt: new Date()
  }
])

insertMany() result

JS
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("64f1a2b3c4d5e6f7a8b9c0d2"),
    '1': ObjectId("64f1a2b3c4d5e6f7a8b9c0d3"),
    '2': ObjectId("64f1a2b3c4d5e6f7a8b9c0d4")
  }
}
Ordered vs Unordered Inserts

By default, insertMany() operates in ordered mode: it processes documents sequentially and stops at the first error, leaving the successfully inserted documents in place. Set ordered: false to switch to unordered mode, which continues processing all documents even when some fail.

Unordered insertMany

JS
// With ordered: false, MongoDB inserts all valid documents
// and reports errors at the end — it does not stop on the first failure.
const result = db.users.insertMany(
  [
    { _id: 1, name: "Bob",   email: "bob@example.com" },
    { _id: 1, name: "Dupe",  email: "dupe@example.com" },  // duplicate _id — will error
    { _id: 2, name: "Carol", email: "carol@example.com" }
  ],
  { ordered: false }
)
// Documents 1 and 3 are inserted; document 2 fails with E11000.
// A BulkWriteError is thrown but insertedIds still contains the successes.

Mode

Behavior

Use Case

ordered: true (default)

Stops at first error. Documents after the failed one are not inserted.

When atomicity matters — e.g., importing a ledger where partial success is worse than no success.

ordered: false

Continues past errors. All valid documents are inserted; errors are collected and thrown together.

When partial success is acceptable — e.g., bulk-importing records where some may be duplicates.

Providing Your Own _id

You can supply any unique BSON value as _id. This is useful when you already have a natural key (username, SKU, ISO code) and want to avoid the overhead of a secondary unique index.

Custom _id values

JS
// String _id — natural key from a business domain
db.countries.insertOne({ _id: "DE", name: "Germany", continent: "Europe" })

// Integer _id — deterministic, human-readable
db.settings.insertOne({ _id: 1, featureFlags: { darkMode: true, beta: false } })

// Composite _id — compound natural key as an embedded document
db.inventory.insertMany([
  { _id: { warehouse: "NYC", sku: "WIDGET-42" }, qty: 500 },
  { _id: { warehouse: "LAX", sku: "WIDGET-42" }, qty: 200 }
])
Warning
If you insert a document whose _id already exists in the collection, MongoDB throws WriteError: E11000 duplicate key error collection. Always wrap inserts that use application-managed _id values in a try/catch block.
Inserting with Schema Validation

If a collection has a validator defined, MongoDB checks every inserted document against it. A document that fails validation is rejected (with validationAction: "error") or inserted with a warning (with validationAction: "warn").

Handling validation errors

JS
try {
  db.users.insertOne({
    name: "Bob",
    // email is required by the schema — omitting it causes a validation error
    age: -5   // also invalid: age minimum is 0
  })
} catch (e) {
  if (e.code === 121) {
    // WriteError code 121 = DocumentValidationFailure
    console.error("Document failed schema validation:", e.message)
    // "Document failed validation" + details about which rule failed
  } else {
    throw e   // unexpected error — rethrow
  }
}
Bulk Writes

For high-performance scenarios that mix inserts, updates, and deletes in a single round-trip, use bulkWrite(). It accepts an array of write operation descriptors and executes them efficiently as a single batch.

bulkWrite() for batch operations

JS
const result = db.inventory.bulkWrite([
  // Insert a new document
  {
    insertOne: {
      document: { _id: { warehouse: "CHI", sku: "GADGET-7" }, qty: 300 }
    }
  },
  // Update an existing document
  {
    updateOne: {
      filter: { _id: { warehouse: "NYC", sku: "WIDGET-42" } },
      update: { $inc: { qty: -10 } }
    }
  },
  // Delete a document
  {
    deleteOne: {
      filter: { _id: { warehouse: "LAX", sku: "WIDGET-42" } }
    }
  },
  // Upsert — insert if not found, update if found
  {
    updateOne: {
      filter: { _id: { warehouse: "SEA", sku: "DOOHICKEY-1" } },
      update: { $setOnInsert: { qty: 150, createdAt: new Date() } },
      upsert: true
    }
  }
], { ordered: true })

console.log(result.insertedCount)   // 1
console.log(result.modifiedCount)   // 1
console.log(result.deletedCount)    // 1
console.log(result.upsertedCount)   // 1
Write Concern

The write concern controls when MongoDB considers a write operation complete and acknowledges it back to the client. Choosing the right write concern is a tradeoff between durability and latency.

Write concern options

JS
// Default: wait for the primary to acknowledge (w: 1)
db.orders.insertOne({ item: "Widget", qty: 10 })

// Majority write concern: wait until a majority of replica set members
// have written the document — much stronger durability guarantee
db.orders.insertOne(
  { item: "Widget", qty: 10 },
  { writeConcern: { w: "majority", wtimeout: 5000 } }
)

// Journal acknowledgement: wait until the write is flushed to the journal
db.orders.insertOne(
  { item: "Widget", qty: 10 },
  { writeConcern: { w: 1, j: true } }
)

// Fire and forget: no acknowledgement — fastest but no durability
db.logs.insertOne(
  { level: "debug", msg: "trace event" },
  { writeConcern: { w: 0 } }
)
Note
insertMany() returns an object where insertedIds is a map (index → ObjectId), not an array. To get a specific inserted ID: result.insertedIds[0], result.insertedIds[1], etc.
Tip
When importing large datasets, batch your documents into groups of around 1 000 and call insertMany() once per batch. A single insertMany() with 1 000 documents is orders of magnitude faster than 1 000 individual insertOne() calls because it dramatically reduces network round-trips and server overhead.
Example Insert Session
> use ecommerce
switched to db ecommerce

> db.products.insertOne({ name: "Keyboard", price: 79.99, stock: 50 })
{
  acknowledged: true,
  insertedId: ObjectId('64f2c3d4e5f6a7b8c9d0e1f2')
}

> db.products.insertMany([
...   { name: "Mouse",   price: 29.99, stock: 120 },
...   { name: "Monitor", price: 349.99, stock: 15 }
... ])
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId('64f2c3d4e5f6a7b8c9d0e1f3'),
    '1': ObjectId('64f2c3d4e5f6a7b8c9d0e1f4')
  }
}

> db.products.countDocuments()
3