Memasukkan seratus buku baru dengan seratus panggilan insertOne() berarti seratus kali perjalanan bolak-balik ke server. insertMany() mengerjakan hal yang sama dalam satu perintah: kita kirim sebuah array berisi banyak document, server menyimpan semuanya, lalu melaporkan hasilnya lengkap dengan peta _id. Chapter ini membahas bentuk panggilannya, cara membaca insertedIds, dan satu keputusan penting yang hanya ada di operasi batch: ketika salah satu document gagal, apakah sisanya tetap diproses?

Peta materi Chapter ini:

  • Bentuk panggilan insertMany() dan arti insertedIds.
  • Perilaku bawaan ordered: true yang berhenti di galat pertama.
  • Opsi ordered: false yang melanjutkan document berikutnya.
  • Catatan performa operasi batch.

Bentuk Panggilan dan insertedIds #

insertMany() menerima satu argumen wajib berupa array of document, ditulis [ ... ], plus argumen kedua opsional berisi opsi. Seperti biasa kita mulai dari collection kosong:

js
use latihan_crud
db.buku.drop()

Output yang Dihasilkan:

text
switched to db latihan_crud
true

Lalu simpan empat buku sekaligus — kali ini tanpa _id manual agar kita bisa melihat perilaku bawaannya:

js
db.buku.insertMany([
  { judul: "Bumi", penulis: "Tere Liye", harga: 89000 },
  { judul: "Laut Bercerita", penulis: "Leila S. Chudori", harga: 98000 },
  { judul: "Filosofi Teras", penulis: "Henry Manampiring", harga: 89000 },
  { judul: "Atomic Habits", penulis: "James Clear", harga: 115000 }
])

Output yang Dihasilkan:

text
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId('6ad385b1c1391103224626e1'),
    '1': ObjectId('6ad385b1c1391103224626e2'),
    '2': ObjectId('6ad385b1c1391103224626e3'),
    '3': ObjectId('6ad385b1c1391103224626e4')
  }
}

Hasilnya bertipe InsertManyResult. Dua bagian pentingnya:

  1. acknowledged: true — sama seperti pada insertOne(), server mengonfirmasi seluruh penulisan yang diminta.
  2. insertedIds — object yang memetakan posisi array ke _id yang tersimpan: kunci '0' adalah document pertama, '1' kedua, dan seterusnya. Karena kita tidak mengirim _id, semua nilainya adalah ObjectId baru.

Pemetaan posisi ini penting saat membaca laporan kegagalan, karena galat batch selalu menyebut posisi (index) document bermasalah — kita akan melihatnya sebentar lagi. Urutan array juga menjadi urutan penyimpanan: document pertama masuk lebih dulu, dan inilah urutan yang kita lihat saat membacanya kembali.

Ordered: Berhenti di Galat Pertama #

Secara bawaan, insertMany() berjalan ordered — document diproses berurutan sesuai posisi array, dan operasi berhenti total di kegagalan pertama. Semua document setelah posisi gagal tidak pernah dikirim ke server. Kita buktikan dengan sengaja membuat duplikat _id di tengah array; _id manual dipakai di sini supaya tabrakan bisa dipastikan:

js
db.buku.insertMany([
  { _id: "b-101", judul: "Rumah Kaca", penulis: "Tere Liye", harga: 72000 },
  { _id: "b-101", judul: "Rumah Kaca (salinan)", penulis: "Tere Liye", harga: 72000 },
  { _id: "b-102", judul: "Sang Pemimpi", penulis: "Andrea Hirata", harga: 65000 }
])

Output yang Dihasilkan:

text
Uncaught:

MongoBulkWriteError: E11000 duplicate key error collection: latihan_crud.buku index: _id_ dup key: { _id: "b-101" }
Result: BulkWriteResult {
  insertedCount: 1,
  matchedCount: 0,
  modifiedCount: 0,
  deletedCount: 0,
  upsertedCount: 0,
  upsertedIds: {},
  insertedIds: { '0': 'b-101' }
}
Write Errors: [
  WriteError {
    err: {
      index: 1,
      code: 11000,
      errmsg: 'E11000 duplicate key error collection: latihan_crud.buku index: _id_ dup key: { _id: "b-101" }',
      errInfo: undefined,
      op: {
        _id: 'b-101',
        judul: 'Rumah Kaca (salinan)',
        penulis: 'Tere Liye',
        harga: 72000
      }
    }
  }
]

Ini jenis keluaran baru, jadi mari kita bedah pelan-pelan:

  1. MongoBulkWriteError — galat yang dibungkus mongosh saat operasi batch menyimpan sebagian data saja.
  2. insertedCount: 1 — hanya document posisi '0' (Rumah Kaca) yang tersimpan; duplikat di posisi '1' ditolak kode E11000 (ingat index _id_ dari Chapter insertOne()).
  3. insertedIds: { '0': 'b-101' } — peta hasil hanya berisi posisi yang berhasil.
  4. Write Errors memuat detail per document gagal: index: 1 (posisi array), code: 11000, serta op berisi document yang ditolak.
  5. Sang Pemimpi tidak tersimpan sama sekali — buktinya di bawah — karena eksekusi berhenti sebelum posisi '2' sempat diproses.
js
db.buku.find()

Output yang Dihasilkan:

text
[
  {
    _id: ObjectId('6ad385b1c1391103224626e1'),
    judul: 'Bumi',
    penulis: 'Tere Liye',
    harga: 89000
  },
  {
    _id: ObjectId('6ad385b1c1391103224626e2'),
    judul: 'Laut Bercerita',
    penulis: 'Leila S. Chudori',
    harga: 98000
  },
  {
    _id: ObjectId('6ad385b1c1391103224626e3'),
    judul: 'Filosofi Teras',
    penulis: 'Henry Manampiring',
    harga: 89000
  },
  {
    _id: ObjectId('6ad385b1c1391103224626e4'),
    judul: 'Atomic Habits',
    penulis: 'James Clear',
    harga: 115000
  },
  {
    _id: 'b-101',
    judul: 'Rumah Kaca',
    penulis: 'Tere Liye',
    harga: 72000
  }
]

Collection berisi lima document: empat dari batch pertama plus satu-satunya penyelamat batch kedua. Sang Pemimpi absen karena ordered insert berhenti di galat.

Unordered: Lanjut Meski Ada yang Gagal #

Mengubah opsinya menjadi { ordered: false } membalik keputusan itu: server tetap memproses semua document yang tersisa meskipun ada yang gagal. Galat tetap dilaporkan, tetapi kegagalan satu document tidak lagi menghentikan sisanya:

js
db.buku.insertMany([
  { _id: "b-103", judul: "Sherlock Holmes", penulis: "Arthur Conan Doyle", harga: 75000 },
  { _id: "b-101", judul: "Rumah Kaca (salinan)", penulis: "Tere Liye", harga: 72000 },
  { _id: "b-104", judul: "Kamus Bahasa Indonesia", penulis: "Badan Bahasa", harga: 55000 }
], { ordered: false })

Output yang Dihasilkan:

text
Uncaught:

MongoBulkWriteError: E11000 duplicate key error collection: latihan_crud.buku index: _id_ dup key: { _id: "b-101" }
Result: BulkWriteResult {
  insertedCount: 2,
  matchedCount: 0,
  modifiedCount: 0,
  deletedCount: 0,
  upsertedCount: 0,
  upsertedIds: {},
  insertedIds: { '0': 'b-103', '2': 'b-104' }
}
Write Errors: [
  WriteError {
    err: {
      index: 1,
      code: 11000,
      errmsg: 'E11000 duplicate key error collection: latihan_crud.buku index: _id_ dup key: { _id: "b-101" }',
      errInfo: undefined,
      op: {
        _id: 'b-101',
        judul: 'Rumah Kaca (salinan)',
        penulis: 'Tere Liye',
        harga: 72000
      }
    }
  }
]
js
db.buku.find()

Output yang Dihasilkan:

text
[
  {
    _id: ObjectId('6ad385b1c1391103224626e1'),
    judul: 'Bumi',
    penulis: 'Tere Liye',
    harga: 89000
  },
  {
    _id: ObjectId('6ad385b1c1391103224626e2'),
    judul: 'Laut Bercerita',
    penulis: 'Leila S. Chudori',
    harga: 98000
  },
  {
    _id: ObjectId('6ad385b1c1391103224626e3'),
    judul: 'Filosofi Teras',
    penulis: 'Henry Manampiring',
    harga: 89000
  },
  {
    _id: ObjectId('6ad385b1c1391103224626e4'),
    judul: 'Atomic Habits',
    penulis: 'James Clear',
    harga: 115000
  },
  {
    _id: 'b-101',
    judul: 'Rumah Kaca',
    penulis: 'Tere Liye',
    harga: 72000
  },
  {
    _id: 'b-103',
    judul: 'Sherlock Holmes',
    penulis: 'Arthur Conan Doyle',
    harga: 75000
  },
  {
    _id: 'b-104',
    judul: 'Kamus Bahasa Indonesia',
    penulis: 'Badan Bahasa',
    harga: 55000
  }
]

Sekarang insertedCount: 2 dan insertedIds memuat posisi '0' serta '2' — hanya duplikat di posisi '1' yang gagal, sementara Kamus Bahasa Indonesia di posisi '2' tetap tersimpan. Collection akhirnya berisi tujuh document.

Catatan Performa #

Kapan insertMany() lebih unggul dibanding insertOne() berulang? Prinsipnya sederhana: setiap panggilan method adalah satu perjalanan jaringan ke server, dan perjalanan itulah komponen termahal dari operasi tulis. Dengan batch, ratusan document menumpuk dalam sedikit perjalanan.

  • insertOne() dalam loop 1.000 kali = hingga 1.000 perjalanan bolak-balik.
  • insertMany() dengan 1.000 document = sedikit perjalanan jaringan saja.

Selain hemat jaringan, batch juga mengurangi beban koordinasi server: satu rangkaian penulisan dieksekusi dalam kesempatan yang sama alih-alih 1.000 kesempatan terpisah. Dalam praktik, selisihnya terasa langsung pada import data awal dan pengisian katalog.

Ada dua batas yang perlu diingat: satu document maksimum 16 MB (batas BSON), dan satu operasi insertMany() di mongosh dibatasi 100.000 document. Untuk jutaan baris dari file CSV atau JSON, alat yang tepat bukan shell melainkan mongoimport, yang dibahas di Section Backup dan Recovery.

Sebagai penutup, bersihkan database latihan:

js
db.dropDatabase()

Output yang Dihasilkan:

text
{ ok: 1, dropped: 'latihan_crud' }

Rangkuman #

  • Bentuk panggilan: db.<collection>.insertMany([<document>, ...]) dengan opsi kedua opsional.
  • insertedIds memetakan posisi array ke _id tersimpan — kunci bacaan untuk laporan kegagalan.
  • Bawaan ordered: true: eksekusi berhenti di galat pertama; document setelahnya tidak diproses.
  • ordered: false: document lain tetap diproses, tetapi galat tetap dilaporkan dan harus ditangani.
  • Batch menghemat perjalanan jaringan; batasnya 16 MB per document dan 100.000 document per operasi.

Kedua pintu Create sudah terbuka. Chapter berikutnya berpindah ke huruf R — membaca data kembali dengan find().