0Pricing
MongoDB Academy · 강의

insertOne 및 insertMany

단일 문서와 여러 문서를 삽입하고 각 작업이 반환하는 자동 생성 _id 필드를 확인합니다.

insertOne 및 insertMany은(는) CoddyKit의 무료 MongoDB Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 MongoDB Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. MongoDB Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

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.

자주 묻는 질문

“insertOne 및 insertMany” 강의는 무료인가요?

네 — “insertOne 및 insertMany” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 MongoDB Academy 강의 전체를 잠금 해제할 수 있습니다. MongoDB Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“insertOne 및 insertMany”에서 뭘 배우나요?

단일 문서와 여러 문서를 삽입하고 각 작업이 반환하는 자동 생성 _id 필드를 확인합니다. 브라우저에서 직접 실행하는 실습 코드로 MongoDB Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

MongoDB Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 MongoDB Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“insertOne 및 insertMany” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 MongoDB Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 MongoDB Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. insertOne 및 insertMany
  2. findOne과 find 비교: 커서 이해하기
  3. 중첩 필드와 배열 쿼리하기
  4. Node.js 드라이버로 문서 읽기
← MongoDB Academy(으)로 돌아가기