0Pricing
MongoDB Academy · Pelajaran

insertOne dan insertMany

Sisipkan dokumen tunggal dan secara massal, lalu periksa bidang _id yang dibuat otomatis dan dikembalikan oleh setiap operasi.

insertOne dan insertMany adalah pelajaran MongoDB Academy gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar MongoDB Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus MongoDB Academy mencakup 4 pelajaran total.

Bagian dari pelajaran ini belum diterjemahkan dan ditampilkan dalam bahasa Inggris.

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.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “insertOne dan insertMany” gratis?

Ya — teks lengkap “insertOne dan insertMany” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus MongoDB Academy, upgrade ke CoddyKit PRO. Kursus MongoDB Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “insertOne dan insertMany”?

Sisipkan dokumen tunggal dan secara massal, lalu periksa bidang _id yang dibuat otomatis dan dikembalikan oleh setiap operasi. Kamu berlatih MongoDB Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai MongoDB Academy?

Tidak diperlukan pengalaman sebelumnya. MongoDB Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.

Berapa lama pelajaran “insertOne dan insertMany” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran MongoDB Academy ini?

Ya. Setiap pelajaran MongoDB Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. insertOne dan insertMany
  2. findOne vs find: Penjelasan Kursor
  3. Membuat Kueri Bidang Bertingkat dan Array
  4. Membaca Dokumen dengan Driver Node.js
← Kembali ke MongoDB Academy