Verifikasi instalasi di Section sebelumnya sudah membuktikan siklus tulis-baca bekerja. Sekarang kita masuk ke pertanyaan yang lebih mendasar: ke mana persisnya data itu tersimpan? MongoDB menyusun penyimpanan dalam hierarki yang sederhana — server menampung database, database menampung collection, dan collection menampung document — dan hampir semua perintah mongosh bergantung pada posisi kita di dalam hierarki tersebut.
Peta materi Chapter ini:
- Hierarki penyimpanan dan konsep namespace
<database>.<collection>. - Pembuatan lazy: database dan collection baru hanya tercipta saat data pertama ditulis.
- Pembuatan eksplisit dengan
db.createCollection(), termasuk opsicapped. - Aturan penamaan untuk database dan collection beserta galat yang muncul jika dilanggar.
Hierarki Penyimpanan dan Namespace #
Satu proses mongod (satu deployment) bisa menampung banyak database yang saling terpisah, dan setiap database bisa memiliki banyak collection. Ilustrasi berikut memakai nama yang akan kita gunakan sepanjang Chapter:
Gabungan nama database dan nama collection membentuk namespace lengkap sebuah collection, ditulis dengan format <database>.<collection> — misalnya latihan_toko.produk. Namespace inilah identitas collection di level server, dan panjangnya dibatasi 255 byte untuk collection biasa (235 byte untuk collection yang di-shard). Identitas tersebut bisa kita lihat langsung lewat db.<collection>.stats().ns begitu collection pertama kita dibuat nanti.
Membuat Database dengan use #
Berbeda dengan database relasional, MongoDB tidak punya perintah khusus “buat database”. Kita hanya berpindah konteks dengan use, dan database baru belum tercipta apa-apa:
use latihan_tokoOutput yang Dihasilkan:
switched to db latihan_tokoShell mengonfirmasi perpindahan konteks, tetapi belum ada satu byte pun yang ditulis ke disk. Buktikan dengan memeriksa isi server dan isi database aktif:
show dbs
db.getCollectionNames()Output yang Dihasilkan:
admin 80.00 KiB
config 408.00 KiB
local 564.00 KiB
[]Daftar database hanya menampilkan admin, config, dan local — database bawaan yang sudah kita kenal di Chapter Verifikasi Instalasi — dan latihan_toko belum terdaftar. Ukuran config dan local berubah mengikuti aktivitas internal server, jadi nilai KiB di mesin kita boleh sedikit berbeda. Array kosong dari db.getCollectionNames() juga menegaskan bahwa database aktif belum memiliki satu collection pun. Inilah yang disebut lazy creation: use hanya mengalihkan konteks, bukan membuat struktur penyimpanan.
Database dan collection benar-benar tercipta saat operasi tulis pertama menyentuhnya:
db.stok.insertOne({ nama: "Kopi Gayo", jumlah: 40 })Output yang Dihasilkan:
{
acknowledged: true,
insertedId: ObjectId('6ad3806d1a3d37e015bb2e41')
}Satu insertOne ke collection stok sekaligus membuat collection stok dan database latihan_toko. Periksa kembali:
show dbs
show collectionsOutput yang Dihasilkan:
admin 80.00 KiB
config 408.00 KiB
latihan_toko 8.00 KiB
local 564.00 KiB
stoklatihan_toko kini muncul di daftar database dengan ukuran awal 8 KiB, dan stok terdaftar sebagai satu-satunya collection di dalamnya. Perhatikan bahwa stok tercipta tanpa perintah pembuatan apa pun — MongoDB membuat collection secara implisit begitu document pertama ditulis ke dalamnya.
Membuat Collection Secara Eksplisit #
Pembuatan implisit memang praktis, tetapi kita kadang perlu membuat collection lebih dulu — misalnya untuk menetapkan opsi khusus. Untuk itu ada db.createCollection():
db.createCollection("produk")Output yang Dihasilkan:
{ ok: 1 }Balasan { ok: 1 } menandakan collection produk berhasil dibuat dan langsung tersedia meski belum berisi document apa pun. Sekarang kita bisa memeriksa namespace lengkapnya:
db.produk.stats().nsOutput yang Dihasilkan:
latihan_toko.produkBandingkan dengan stok yang baru muncul setelah insert — keduanya kini terdaftar bersama:
db.getCollectionNames()Output yang Dihasilkan:
[ 'produk', 'stok' ]Kekuatan utama db.createCollection() ada di parameter opsi keduanya. Contoh paling dikenal adalah capped collection — collection berukuran tetap yang secara otomatis membuang document tertua saat kapasitasnya penuh, cocok untuk log dan data berumur pendek:
db.createCollection("log", { capped: true, size: 4096, max: 2 })Output yang Dihasilkan:
{ ok: 1 }Mari kita bedah opsi tersebut:
capped: truemengaktifkan mode collection tetap; tanpa opsi ini, collection tumbuh tanpa batas.size: 4096menetapkan batas total 4096 byte. Nilaisizewajib ada saatcappedaktif.max: 2menetapkan batas jumlah document. Saat salah satu batas tercapai, document tertua dihapus otomatis untuk memberi ruang.
Opsi yang tersimpan bisa kita lihat kembali lewat db.getCollectionInfos():
db.getCollectionInfos({ name: "log" })Output yang Dihasilkan:
[
{
name: 'log',
type: 'collection',
options: { capped: true, size: 4096, max: 2 },
info: { readOnly: false, uuid: UUID('a221a290-41d7-446b-8759-ddcc0ae9375b') },
idIndex: { v: 2, key: { _id: 1 }, name: '_id_' }
}
]Perilaku capped bisa dibuktikan langsung. Masukkan tiga document ke dalam log yang dibatasi max: 2, lalu baca isinya:
db.log.insertOne({ pesan: "log ke-1" })
db.log.insertOne({ pesan: "log ke-2" })
db.log.insertOne({ pesan: "log ke-3" })
db.log.find()Output yang Dihasilkan:
{
acknowledged: true,
insertedId: ObjectId('6ad3806e1a3d37e015bb2e42')
}
{
acknowledged: true,
insertedId: ObjectId('6ad3806e1a3d37e015bb2e43')
}
{
acknowledged: true,
insertedId: ObjectId('6ad3806e1a3d37e015bb2e44')
}
[
{ _id: ObjectId('6ad3806e1a3d37e015bb2e43'), pesan: 'log ke-2' },
{ _id: ObjectId('6ad3806e1a3d37e015bb2e44'), pesan: 'log ke-3' }
]Hanya log ke-2 dan log ke-3 yang tersisa — document pertama terhapus otomatis begitu document ketiga masuk. Kita juga bisa memastikan status capped kapan saja:
db.log.isCapped()Output yang Dihasilkan:
trueAturan Penamaan Database dan Collection #
Nama adalah kontrak: sekali data tersimpan, nama database dan collection menjadi bagian dari namespace yang dirujuk semua aplikasi. MongoDB menerapkan aturan berbeda untuk keduanya:
| Aspek | Database | Collection |
|---|---|---|
| Nama kosong | Ditolak | Ditolak |
| Karakter terlarang (Linux) | / \ . " $ dan karakter null | $ dan karakter null |
| Karakter terlarang (Windows) | Ditambah * < > : ` | ?` |
| Panjang maksimum | Kurang dari 64 byte | Namespace total ≤ 255 byte |
| Awalan terlarang | — | system. (dipesan untuk internal) |
| Kapitalisasi | Case-sensitive; jangan andalkan huruf besar-kecil untuk membedakan nama | Case-sensitive |
Dua catatan penting dari tabel tersebut. Pertama, batas karakter Windows lebih ketat karena sistem berkasnya; agar aman lintas platform, hindari semua karakter terlarang dan gunakan huruf kecil. Kedua, awalan system. dipesan untuk collection internal MongoDB — membuat collection dengan awalan tersebut akan ditolak.
Pelanggaran aturan langsung terlihat sebagai galat. Coba dua nama yang melanggar:
db.createCollection("produk$stok")
db.getSiblingDB("toko baru").createCollection("x")Output yang Dihasilkan:
Uncaught
MongoServerError[InvalidNamespace]: Invalid collection name: produk$stok
Uncaught
MongoshInvalidInputError: [COMMON-10001] Invalid database name: toko baruServer menolak produk$stok karena nama collection tidak boleh mengandung $, sedangkan mongosh menolak nama database toko baru lebih dulu di sisi klien karena mengandung spasi. Untuk nama collection yang diawali angka atau memakai tanda hubung, akses dengan kurung siku atau db.getCollection() agar mongosh tidak salah mengurai — misalnya db["2024-orders"] atau db.getCollection("log-aktif").
Rangkuman #
| Kegiatan | Perintah | Catatan |
|---|---|---|
| Berpindah database | use latihan_toko | Tidak membuat apa pun |
| Melihat daftar database | show dbs | Database baru muncul setelah tulis pertama |
| Melihat collection | show collections / db.getCollectionNames() | — |
| Membuat collection implisit | db.stok.insertOne({...}) | Collection + database tercipta otomatis |
| Membuat collection eksplisit | db.createCollection("log", {...}) | Bisa membawa opsi |
| Collection berukuran tetap | { capped: true, size, max } | Document tertua terhapus otomatis |
| Namespace | db.produk.stats().ns | latihan_toko.produk, maksimum 255 byte |
Sebagai penutup, hapus database latihan ini dan pastikan server kembali bersih:
db.dropDatabase()
show dbsOutput yang Dihasilkan:
{ ok: 1, dropped: 'latihan_toko' }
admin 80.00 KiB
config 408.00 KiB
local 564.00 KiBDatabase, collection, dan document kini punya tempat yang jelas dalam peta mental kita. Chapter berikutnya membedah isi collection itu sendiri: document dan format biner BSON yang menyimpannya.