0Pricing
MongoDB Academy · Lección

insertOne e insertMany

Insertará documentos individuales y en bloque, y examinará el campo _id generado automáticamente que devuelve cada operación.

insertOne e insertMany es una lección gratuita de MongoDB Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de MongoDB Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de MongoDB Academy incluye 4 lecciones en total.

Partes de esta lección aún no han sido traducidas y se muestran en inglés.

The Two Insert Methods

MongoDB provides two methods for adding documents to a collection:

  • insertOne(doc) — inserts a single document and returns an object with acknowledged and insertedId
  • insertMany(docs) — inserts an array of documents and returns acknowledged and insertedIds (an object mapping array index to generated _id)

Both methods are synchronous in mongosh and return Promises in Node.js driver code. Always await them in async Node.js functions to handle errors properly.

// insertOne
const res1 = await db.collection('users').insertOne({ name: 'Alice', age: 28 });
console.log(res1.insertedId); // ObjectId('...')

// insertMany
const res2 = await db.collection('users').insertMany([
  { name: 'Bob', age: 32 },
  { name: 'Carol', age: 25 }
]);
console.log(res2.insertedIds);
// { '0': ObjectId('...'), '1': ObjectId('...') }

Auto-Generated ObjectId

When you insert a document without an _id field, MongoDB generates an ObjectId automatically. The ObjectId is a 12-byte BSON type whose structure ensures global uniqueness across distributed nodes without a central counter:

  • Bytes 0-3: Unix timestamp (seconds) — allows approximate sort by insertion time
  • Bytes 4-8: Random value (generated once per process)
  • Bytes 9-11: Incrementing counter (initialized to a random value)

This design means two different servers inserting documents at the same millisecond will still produce different ObjectIds, making distributed inserts collision-free.

// Auto-generated ObjectId on insert
db.items.insertOne({ name: 'Widget' });
// { acknowledged: true, insertedId: ObjectId('64a2f3b1c9e7e12345678901') }

// Extract timestamp from an ObjectId
const id = ObjectId('64a2f3b1c9e7e12345678901');
print(id.getTimestamp());
// ISODate('2023-07-03T10:15:29.000Z')

// Sorting by _id gives approximate insertion order
db.items.find({}).sort({ _id: 1 });

Supplying Your Own _id

You can override the auto-generated ObjectId by providing your own _id value. Any BSON type works: string, number, UUID, or even a nested object. The only requirement is that the value must be unique within the collection.

Custom _ids are useful when you already have a natural unique key—a product SKU, a username slug, or an external system's ID. However, avoid monotonically incrementing integers as custom _ids in sharded clusters—they create write hot spots on the shard that holds the highest key range.

// String _id (natural key)
db.products.insertOne({
  _id: 'SKU-WH-BLK-42',
  name: 'Wireless Headphones Black',
  price: 79.99
});

// Number _id
db.categories.insertOne({ _id: 100, name: 'Electronics' });

// Duplicate _id throws E11000 duplicate key error:
db.categories.insertOne({ _id: 100, name: 'Gadgets' });
// MongoServerError: E11000 duplicate key error

insertMany: Bulk Inserts

insertMany accepts an array of documents. It is significantly more efficient than calling insertOne in a loop because it sends all documents in a single network round-trip and MongoDB can batch the writes internally.

By default, insertMany inserts documents in ordered mode: if one document fails validation or has a duplicate _id, the operation stops and does not insert remaining documents. Set { ordered: false } as the second argument to switch to unordered mode, where MongoDB continues inserting the rest even if some fail.

// Ordered insertMany (default) - stops on first error
db.users.insertMany([
  { name: 'Alice' },
  { name: 'Bob' },
  { name: 'Carol' }
]);

// Unordered insertMany - continues after errors
db.users.insertMany(
  [
    { _id: 1, name: 'Alice' },
    { _id: 1, name: 'Duplicate' },  // Will fail (dup key)
    { _id: 2, name: 'Bob' }         // Still inserted in unordered mode
  ],
  { ordered: false }
);

Inspecting the insertedIds Object

The result object from insertMany contains insertedIds as an object (not an array) where keys are the array index strings and values are the generated ObjectIds. This lets you correlate each input document with its resulting _id.

In Node.js, you often map the inserted documents back to their IDs for further processing—for example, creating related documents in another collection that reference these new _ids.

const docs = [
  { name: 'Widget A', price: 10 },
  { name: 'Widget B', price: 20 },
  { name: 'Widget C', price: 30 }
];

const result = await db.collection('products').insertMany(docs);

console.log(result.insertedCount); // 3
console.log(result.insertedIds);
// {
//   '0': ObjectId('...'),
//   '1': ObjectId('...'),
//   '2': ObjectId('...')
// }

// Attach _ids back to original docs
docs.forEach((doc, i) => {
  doc._id = result.insertedIds[i];
});

WriteConcern: Controlling Durability

By default, insertOne and insertMany use the connection's default write concern—usually w: 1, meaning the primary acknowledges the write. You can override this per-operation:

  • { w: 0 } — fire-and-forget, no acknowledgment (fastest, unsafe)
  • { w: 1 } — acknowledged by primary (default)
  • { w: 'majority' } — acknowledged by majority of replica set members (safest)
  • { j: true } — additionally requires the write to be flushed to the journal on disk
// Safe insert: confirmed by majority of replica set + journaled
await db.collection('orders').insertOne(
  { orderId: 'ORD-001', total: 99.99, status: 'pending' },
  { writeConcern: { w: 'majority', j: true } }
);
// Slower than w:1 but guaranteed durable even if primary crashes

Handling Duplicate Key Errors

MongoDB throws a duplicate key error (E11000) when an insert violates a unique index—most commonly the _id uniqueness requirement, but also any user-defined unique index. In Node.js, this throws a MongoServerError with code 11000.

Always wrap inserts in try/catch when duplicate key errors are expected (e.g., upserting users by email). Check the error code to distinguish duplicates from other write errors and respond appropriately—return 409 Conflict from an API, or update the existing document instead.

try {
  await db.collection('users').insertOne({
    email: 'alice@example.com',
    name: 'Alice'
  });
} catch (err) {
  if (err.code === 11000) {
    // Duplicate key - email already exists
    console.log('User with this email already exists');
    // Respond with HTTP 409 Conflict in an API
  } else {
    throw err;  // Re-throw unexpected errors
  }
}

Seeding Test Data With Loops

A common development task is seeding a collection with realistic test data. You can do this directly in mongosh using a JavaScript loop, or write a Node.js script. For large datasets, use insertMany in batches of 500-1000 documents rather than one massive array—this avoids memory issues and allows progress monitoring.

For generating realistic fake data in Node.js, the @faker-js/faker library is widely used. It generates realistic names, emails, addresses, dates, and many other field types, making test data indistinguishable from real data.

// Seed 100 test users in mongosh
const users = [];
for (let i = 1; i <= 100; i++) {
  users.push({
    name: 'User ' + i,
    email: 'user' + i + '@example.com',
    age: 18 + (i % 50),
    active: i % 3 !== 0,
    createdAt: new Date(Date.now() - i * 86400000)
  });
}
db.users.insertMany(users);
// { acknowledged: true, insertedCount: 100 }

Checking Inserted Documents

After an insert, always verify your data landed correctly. Useful verification commands:

  • db.collection.countDocuments({}) — total count
  • db.collection.findOne({ _id: insertedId }) — verify a specific document by its returned _id
  • db.collection.find({}).sort({ _id: -1 }).limit(5) — see the 5 most recently inserted documents

In automated tests, verify not just that the insert succeeded (no error thrown) but also that the stored document has the expected field values—subtle type coercions or middleware transformations can change fields during insert.

// Insert and immediately verify
const { insertedId } = await db.collection('orders').insertOne({
  customerId: ObjectId('...'),
  items: [{ sku: 'A1', qty: 2 }],
  total: 39.98,
  status: 'pending'
});

const stored = await db.collection('orders').findOne({ _id: insertedId });
console.log(stored.status);   // 'pending'
console.log(stored.total);    // 39.98

Transactions and Multiple Inserts

When you need to insert documents into multiple collections atomically—all succeed or all fail together—use a multi-document transaction. Without a transaction, if the second insert fails after the first succeeds, your data is in an inconsistent state.

Transactions add latency and should be reserved for cases where atomicity is truly required. For most single-collection bulk inserts, insertMany with ordered mode provides sufficient atomicity at the collection level (either all documents before the failure are inserted, or none if rollback is needed).

// Atomic insert across two collections using a transaction
const session = client.startSession();
try {
  await session.withTransaction(async () => {
    await db.collection('orders').insertOne(
      { total: 99.99, customerId: custId }, { session }
    );
    await db.collection('orderEvents').insertOne(
      { type: 'created', orderId: ordId }, { session }
    );
  });
} finally {
  await session.endSession();
}

Performance Tip: Bulk Write API

For mixed operations (inserts, updates, deletes) in a single batch, use db.collection.bulkWrite(operations). This is more efficient than separate insertMany + updateMany calls because all operations share a single network round-trip.

Each operation in the array is an object with a key like insertOne, updateOne, deleteOne, etc. The result object summarizes inserted, modified, and deleted counts. bulkWrite also supports ordered/unordered modes just like insertMany.

await db.collection('products').bulkWrite([
  { insertOne: { document: { name: 'New Product', price: 25 } } },
  { updateOne: {
      filter: { name: 'Old Product' },
      update: { $set: { price: 15 } }
  }},
  { deleteOne: { filter: { name: 'Discontinued' } } }
]);
// { insertedCount: 1, modifiedCount: 1, deletedCount: 1 }

Quick Check

Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.

Lesson Recap

In this lesson you learned: insertOne and insertMany are the two insert methods—insertMany is more efficient for bulk data and supports ordered/unordered error handling, ObjectId is auto-generated if you do not supply _id, encoding the insertion timestamp in its first 4 bytes for approximate ordering, and write concern controls durability from fire-and-forget (w:0) to majority-replicated (w:'majority'). Next up we explore the find() cursor in depth and learn how to query nested fields and arrays with dot notation.

Preguntas frecuentes

¿La lección «insertOne e insertMany» es gratis?

Sí — el texto completo de «insertOne e insertMany» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de MongoDB Academy, actualiza a CoddyKit PRO. El curso de MongoDB Academy incluye 4 lecciones en total.

¿Qué aprenderé en «insertOne e insertMany»?

Insertará documentos individuales y en bloque, y examinará el campo _id generado automáticamente que devuelve cada operación. Practicas MongoDB Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar MongoDB Academy?

No se requiere experiencia previa. MongoDB Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «insertOne e insertMany»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de MongoDB Academy?

Sí. Cada lección de MongoDB Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. insertOne e insertMany
  2. findOne frente a find: explicación de los cursores
  3. Consultar campos anidados y arrays
  4. Leer documentos con el controlador de Node.js
← Volver a MongoDB Academy