MongoDB adalah document database: dia menyimpan data dalam bentuk document, struktur mirip objek JSON yang disimpan sebagai BSON (Binary JSON). Document yang sejenis dikumpulkan dalam collection. Bayangin lemari arsip Kedai Senja. Tiap pesanan punya satu map, dan di dalam map itu ada semua kertasnya: siapa pembelinya, apa saja yang dibeli, totalnya. Mapnya adalah document, lacinya adalah collection. Mau lihat pesanan #1? Ambil satu map, selesai.
🧪 Tebakan cepat: di MongoDB, nama Budi disalin ke dalam kedua dokumen pesanannya. Budi ganti nama jadi Budi Santoso, lalu developer menjalankan
db.orders.updateOne({ 'customer._id': 1 }, { $set: { 'customer.name': 'Budi Santoso' } }). Berapa pesanan Budi yang sekarang memakai nama baru: 0, 1, atau 2? Tebak dulu, jawabannya ada di bagian "Embed atau reference".
Istilah SQL dalam bahasa MongoDB
Konsepnya mirip dengan yang sudah kamu kenal di SQL, cuma namanya beda:
| SQL | MongoDB |
|---|---|
| table | collection |
| row | document |
| column | field |
JOIN |
$lookup |
| index | index (sama) |
| primary key | _id |
Setiap document wajib punya _id yang unik di collection-nya. Index juga bekerja seperti di SQL: db.orders.createIndex({ 'items.product': 1 }) membuat pencarian berdasarkan produk gak perlu memeriksa semua dokumen.
Satu pesanan, satu document
Tiga pesanan Kedai Senja yang sama dengan track ini, sebagai collection orders. Begini mongosh (shell MongoDB) mencetak pesanan #1:
kedai> db.orders.findOne({ _id: 1 })
{
_id: 1,
customer: { _id: 1, name: 'Budi' },
items: [
{ product: 'Kopi Susu', price: 18000, qty: 2 },
{ product: 'Roti Bakar', price: 20000, qty: 1 }
],
total: 56000
}
customeradalah embedded document: object di dalam document.itemsadalah array berisi document. Di SQL, ini perlu tabelorder_itemsdanJOIN; di sini satu kali baca sudah dapat semuanya.- Pesanan #3 (Siti) punya field tambahan
catatan: 'kurang manis', dan dua pesanan lain gak punya. Gak perluALTER TABLE: setiap document boleh punya struktur berbeda. Ini yang disebut schema-flexible. - Fleksibel bukan berarti tanpa aturan. Aplikasimu harus siap menghadapi field yang gak ada, dan MongoDB bisa diberi validasi (
$jsonSchema) kalau kamu mau dia menolak data yang salah bentuk.
Mencari dengan find()
find() menerima filter: object yang menyebut field dan syaratnya. Tiga operator yang paling sering:
kedai> db.orders.find({ 'items.product': { $eq: 'Teh Tarik' } })
// cuma pesanan #3
kedai> db.orders.find({ total: { $gt: 30000 } })
// pesanan #1 (56000) dan #3 (33000)
kedai> db.orders.find({ 'items.product': { $in: ['Teh Tarik', 'Roti Bakar'] } })
// pesanan #1 (ada Roti Bakar) dan #3 (ada Teh Tarik)
$eqartinya sama dengan.{ 'customer.name': 'Budi' }adalah singkatan{ 'customer.name': { $eq: 'Budi' } }, dan hasilnya pesanan #1 dan #2.$gtartinya lebih besar dari (greater than). Ada juga$gte,$lt,$lte.$incocok kalau nilainya salah satu dari daftar.- Dot notation (
'items.product') masuk ke dalam embedded document dan array, dan wajib ditulis dalam tanda kutip. Kalau field-nya array, filter cocok begitu satu elemen saja memenuhi syarat. - Kalau gak ada yang cocok, mongosh gak mencetak apa-apa. Lab di halaman ini menjalankan filter seperti ini ke ketiga dokumen dan mencetak hasilnya dalam format mongosh.
Embed atau reference
Ada dua cara menyimpan data yang berhubungan:
- Embed: disalin ke dalam document induknya, seperti
itemsdancustomerdi atas. - Reference: cuma menyimpan
_id-nya, seperti foreign key. Pesanan menyimpancustomer_id: 1, dan data Budi tinggal di collectioncustomers.
Kembali ke tebakan. Nama Budi di-embed di pesanan #1 dan #2. updateOne berhenti di dokumen pertama yang cocok, jadi cuma 1 pesanan yang berubah. Budi sekarang punya dua nama, tanpa error. Itu jawaban tebakannya. Yang benar updateMany, dan mongosh menjawab:
{
acknowledged: true,
insertedId: null,
matchedCount: 2,
modifiedCount: 2,
upsertedCount: 0
}
Dengan reference, cukup db.customers.updateOne({ _id: 1 }, { $set: { name: 'Budi Santoso' } }): 1 document, dan semua pesanan ikut. Bayarannya, membaca pesanan beserta nama pembelinya butuh $lookup, JOIN-nya MongoDB:
db.orders.aggregate([
{ $lookup: { from: 'customers', localField: 'customer_id', foreignField: '_id', as: 'customer' } },
{ $match: { 'customer.name': 'Budi' } }
])
Aturannya: embed jika data sering diakses bersama dan jarang berubah sendiri (item pesanan selalu dibaca bersama pesanannya, dan harga saat beli memang gak boleh ikut berubah). Reference jika data berdiri sendiri, dipakai banyak document, atau bisa tumbuh tanpa batas (pelanggan yang punya puluhan pesanan, komentar di postingan viral). Satu document maksimal 16 MB, jadi array yang terus tumbuh harus jadi reference.
Kapan MongoDB cocok
- Data yang bentuknya beda-beda: katalog (kopi punya ukuran gelas, roti punya rasa selai), CMS, profil.
- Data yang hampir selalu dibaca utuh per document, seperti halaman pesanan.
- Log dan event yang ditulis terus-menerus.
Kurang cocok kalau datanya saling berelasi rumit dan sering ditanya lintas data ("total penjualan per produk per bulan"). Itu kekuatan SQL, dibahas di pelajaran SQL vs NoSQL.
⚠️ Jebakan yang sering ketemu
updateOneuntuk data yang disalin ke banyak document. Sisanya tetap memakai data lama. PakaiupdateMany, atau jadikan reference.- Embed array yang tumbuh tanpa batas. Komentar, log, riwayat: suatu hari document-nya menabrak batas 16 MB.
- Salah ketik nama field.
{ 'item.product': 'Kopi Susu' }(kurang huruf s) gak error, cuma gak menemukan apa-apa. Saat menulis, salah ketik malah membuat field baru diam-diam. - Salah tulis jawaban di latihan. Kembalikan teks huruf kecil persis:
"collection","document","field","index", dan"$lookup"lengkap dengan tanda$.
TL;DR: MongoDB adalah document database: data disimpan sebagai document mirip JSON (BSON) di dalam collection, dan tiap document boleh punya field berbeda tanpa ALTER TABLE. Istilahnya: table jadi collection, row jadi document, column jadi field, JOIN jadi $lookup, index tetap index, primary key jadi _id. find() memakai filter seperti { total: { $gt: 30000 } }, $eq dan $in, dengan dot notation untuk masuk ke embedded document dan array. Embed data yang selalu dibaca bersama dan jarang berubah sendiri; reference data yang berdiri sendiri atau tumbuh tanpa batas. Data yang di-embed di banyak document harus diubah dengan updateMany.