Topik ini membandingkan cara berpikir basis data relasional dengan cara berpikir basis data dokumen pada MongoDB. Pemetaan istilah dibahas lebih dulu, dilanjutkan perbandingan struktur secara visual, lalu diakhiri percobaan menggabungkan dua koleksi dengan $lookup. Setelah membacanya, konsep tabel, baris, dan JOIN pada relasional memiliki padanan yang jelas di sisi dokumen.
Pemetaan istilah#
Kebiasaan pada basis data relasional membagi data ke tabel yang berisi baris dan kolom, sedangkan hubungan antartabel dibangun dengan kunci asing. MongoDB memakai nama yang berbeda untuk gagasan yang mirip, dengan perbedaan perilaku yang penting pada beberapa padanannya. Pemetaan berikut menjadi jembatan yang mempercepat pembacaan dokumentasi, karena istilah lama dapat diterjemahkan terlebih dahulu sebelum detail perilakunya dipelajari. Tabel berikut merangkum pemetaan istilah relasional ke istilah MongoDB.
| Relasional | MongoDB | Catatan |
|---|---|---|
| tabel | koleksi | wadah data dengan tema yang sama |
| baris (row) | dokumen | satu unit data utuh |
| kolom (column) | field | pasangan nama dan nilai dalam dokumen |
| kunci asing (foreign key) | referensi ObjectId atau embedding | penghubung data antartabel atau antardokumen |
| JOIN | $lookup atau embedding | penggabungan data terkait saat dibaca |
Tiga baris pertama hanyalah penggantian nama, sedangkan dua baris terakhir memuat perbedaan cara kerja. Pada relasional, hubungan antartabel selalu diwujudkan sebagai kunci asing, lalu digabung kembali dengan JOIN pada saat dibaca. Pada MongoDB, hubungan yang sama dapat ditulis sebagai data yang menempel di dalam dokumen (embedding) atau sebagai referensi berupa ObjectId yang menunjuk dokumen lain, mirip cara kerja kunci asing.
Dua cara menyusun data terkait#
Perbedaan terbesar terletak pada penempatan data yang saling berhubungan. Diagram berikut menampilkan dua tabel relasional bersebelahan dengan satu dokumen MongoDB yang menyimpan data terkait di dalam dirinya.
Pada sisi relasional, data perangkat dan data pengukuran tinggal di dua tabel yang berbeda. Kunci asing perangkat_id menghubungkan keduanya, dan pembacaan satu perangkat beserta seluruh pengukurannya menuntut penggabungan lewat JOIN. Pada sisi dokumen, pengukuran ditulis sebagai array yang menempel pada dokumen perangkat, sehingga satu kali pembacaan sudah menghasilkan data yang utuh.
Strategi embedding dan referensi tidak saling menggantikan. Embedding cocok untuk data yang hampir selalu dibaca bersama induknya, sedangkan referensi cocok untuk data yang dibaca terpisah, dipakai banyak dokumen, atau tumbuh tanpa batas. Keduanya dapat bercampur pada satu basis data sesuai kebutuhan tiap kelompok data, dan penentuan strateginya merupakan bagian dari pekerjaan merancang schema.
Dua koleksi di dalam mongosh#
Contoh berikut membangun dua koleksi pada basis data praktik, yaitu perangkat dan pengukuran. Koleksi dibuat otomatis saat dokumen pertama disisipkan, tanpa pernyataan pembuatan terlebih dahulu. Dokumen perangkat pertama disisipkan dengan insertOne().
use praktik
db.perangkat.insertOne({
nama: "suhu-lab-1",
ruang: "A-101",
tipe: "termohigrometer"
})switched to db praktik
{
acknowledged: true,
insertedId: ObjectId('6ae85c9ef58538f402ce5f47')
}Pengukuran yang merujuk perangkat menyimpan ObjectId perangkat tersebut pada field perangkatId. ObjectId diambil lewat findOne(), lalu disalin ke dua dokumen pengukuran melalui insertMany().
var perangkatLab = db.perangkat.findOne({ nama: "suhu-lab-1" })
db.pengukuran.insertMany([
{ perangkatId: perangkatLab._id, suhuC: 23.8, dicatatPada: new Date("2026-01-12T09:00:00Z") },
{ perangkatId: perangkatLab._id, suhuC: 24.2, dicatatPada: new Date("2026-01-12T09:30:00Z") }
]){
acknowledged: true,
insertedIds: {
'0': ObjectId('6ae85c9ef58538f402ce5f48'),
'1': ObjectId('6ae85c9ef58538f402ce5f49')
}
}show collectionspengukuran
perangkatUrutan pada keluaran mengikuti urutan nama koleksi, dan daftarnya hanya memuat koleksi pada basis data praktik yang sedang dipakai. Koleksi lain pada basis data yang sama akan muncul di daftar ini begitu dokumen pertamanya disisipkan. Dua koleksi di atas cukup membuktikan bahwa pembuatan koleksi terjadi secara implisit tanpa pernyataan khusus.
Menggabungkan data dengan $lookup#
Bahasa query MongoDB tidak memiliki kata JOIN. Penggabungan antarkoleksi tetap mungkin dilakukan, tetapi melalui tahap $lookup pada pipeline agregasi, yaitu rangkaian tahap pemrosesan data yang dijalankan berurutan oleh MongoDB. Tahap ini bekerja mirip JOIN kiri pada SQL. Setiap dokumen pada koleksi asal dipasangkan dengan dokumen-dokumen koleksi tujuan yang nilainya cocok, lalu hasil padanannya ditempel sebagai field array baru.
db.pengukuran.aggregate([
{
$lookup: {
from: "perangkat",
localField: "perangkatId",
foreignField: "_id",
as: "infoPerangkat"
}
}
])[
{
_id: ObjectId('6ae85c9ef58538f402ce5f48'),
perangkatId: ObjectId('6ae85c9ef58538f402ce5f47'),
suhuC: 23.8,
dicatatPada: ISODate('2026-01-12T09:00:00.000Z'),
infoPerangkat: [
{
_id: ObjectId('6ae85c9ef58538f402ce5f47'),
nama: 'suhu-lab-1',
ruang: 'A-101',
tipe: 'termohigrometer'
}
]
},
{
_id: ObjectId('6ae85c9ef58538f402ce5f49'),
perangkatId: ObjectId('6ae85c9ef58538f402ce5f47'),
suhuC: 24.2,
dicatatPada: ISODate('2026-01-12T09:30:00.000Z'),
infoPerangkat: [
{
_id: ObjectId('6ae85c9ef58538f402ce5f47'),
nama: 'suhu-lab-1',
ruang: 'A-101',
tipe: 'termohigrometer'
}
]
}
]Setiap dokumen pengukuran pada keluaran kini membawa field infoPerangkat berupa array yang berisi dokumen perangkat hasil kecocokan. Bentuk array wajar terjadi karena satu dokumen boleh dipasangkan dengan lebih dari satu dokumen tujuan. Untuk saat ini, cukup dipahami bahwa penggabungan ala JOIN tersedia melalui $lookup, dengan bentuk hasil berupa array.
Tahap $lookup dijalankan pada saat query berlangsung, sehingga biayanya terasa pada koleksi yang sangat besar. Perancangan data yang mengurangi kebutuhan penggabungan sering kali lebih murah daripada mengandalkan $lookup pada setiap pembacaan. Pertimbangan biaya semacam ini menjadi penting segera setelah volume data bertambah.
Kesalahan umum#
Kesalahan pertama yang sering terjadi adalah mengira $lookup mengalami error karena keluarannya berupa array, bukan satu dokumen. Bentuk array pada hasil $lookup memang disengaja, sehingga kekhawatiran semacam itu tidak perlu. Apabila isinya memang dipastikan tunggal, array tersebut cukup dibaca pada elemen pertamanya, sedangkan tahap $unwind pada pipeline agregasi menyediakan cara yang lebih umum untuk mengurainya.
Kesalahan kedua adalah menyalin pola relasional secara utuh, yaitu memecah data ke banyak koleksi lalu menggabungkannya dengan banyak $lookup pada setiap pembacaan. Bila sekelompok data hampir selalu dibaca bersama, menyimpannya sebagai satu dokumen lebih sederhana sekaligus lebih cepat. Pemecahan ke koleksi terpisah baru memberi manfaat ketika data memang dibaca terpisah atau tumbuh besar secara independen.
Ringkasan#
- Tabel, baris, kolom, dan kunci asing pada relasional berpadanan dengan koleksi, dokumen, field, serta referensi ObjectId atau embedding pada MongoDB.
- MongoDB tidak memiliki kata JOIN pada bahasa querynya, sehingga data terkait disusun melalui embedding, referensi, atau tahap
$lookuppada pipeline agregasi. - Koleksi dibuat otomatis saat dokumen pertama disisipkan, tanpa pernyataan pembuatan terlebih dahulu.
$lookupmenghasilkan gabungan ala JOIN kiri yang bentuk hasilnya berupa array.
Referensi#
- $lookup (aggregation) — MongoDB Manual
— Dokumen resmi tahap
$lookupbeserta perilaku penggabungannya. - Data Modeling Introduction — MongoDB Manual — Pengantar resmi cara memodelkan hubungan data pada MongoDB.