Belajar MongoDB - Schema Design Patterns & Best Practices
Episode 6 of 21

Belajar MongoDB - Schema Design Patterns & Best Practices

Memahami bahwa flexible schema bukan berarti tanpa desain, menguasai prinsip data locality dan kebiasaan menulis skema berorientasi query, serta mengenali anti-pattern seperti massive arrays dan excessive nesting beserta solusinya.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Sampai episode 5, kalian sudah mahir menulis query dalam berbagai bentuk. Sekarang tiba waktunya pertanyaan yang lebih mendasar: bagaimana seharusnya data disusun? Ini topik yang paling sering diabaikan — banyak developer merasa "schemaless" berarti bebas menaruh data sesuka hati. Faktanya, justru karena tidak ada schema kaku, kalian harus lebih disiplin dalam merancangnya.

Episode 6 menanamkan cara berpikir desainer schema MongoDB. Roadmap-nya: pertama kita luruskan mitos "schemaless = tanpa desain", kedua kita pahami prinsip emas data locality, ketiga kita pelajari bahwa schema harus mengikuti access pattern, dan keempat kita bedah anti-pattern paling umum beserta solusinya. Akhir episode, kalian akan melihat schema MongoDB sebagai keputusan arsitektur, bukan sekadar tempat menumpuk JSON.

Flexible Schema Bukan Berarti Tanpa Desain

Ada kesalahpahaman berbahaya: karena MongoDB tidak memaksa schema, maka desain tidak penting. Ini keliru total. Flexible schema justru memindahkan tanggung jawab dari database ke kalian sebagai arsitek data. Database tidak akan memprotes kalau kalian menyimpan email sebagai array alih-alih string — tapi aplikasi kalian akan runtuh saat dipakai memproduksi.

Bayangkan perbedaan ini: di RDBMS, schema adalah batasan yang melindungi kalian dari data kacau; di MongoDB, schema adalah keputusan yang harus kalian buat dengan kesadaran penuh. Pertanyaan kunci yang harus kalian jawab sebelum menulis dokumen pertama:

  • Siapa yang membaca data ini dan dalam bentuk apa?
  • Seberapa sering data di-update dan di mana field yang berubah?
  • Berapa besar pertumbuhan data per dokumen?

Jika kalian bisa menjawab tiga pertanyaan itu, kalian sudah punya dasar desain yang jauh lebih baik daripada kebanyakan developer yang asal menulis.

Salah satu cara menyalurkan disiplin desain adalah mendokumentasikan schema. Bisa lewat file JSON Schema untuk validasi (kita bahas di episode 8), bisa lewat library seperti Zod atau Mongoose di sisi aplikasi. Kuncinya: konsistensi struktur field — penamaan, tipe data, dan unit — harus disepakati lintas seluruh tim, atau aplikasi akan kacau saat dua service membaca field yang sama dengan asumsi berbeda.

Prinsip Utama: Data Locality

"Data yang diakses bersama harus disimpan bersama"

Inilah prinsip nomor satu desain schema MongoDB, sering disebut data locality. Di RDBMS, kalian menormalkan data lalu menggabungkannya dengan JOIN saat membaca. Di MongoDB, penggabungan itu mahal — lebih baik meletakkan data yang sering dibaca bersamaan di dokumen yang sama.

Contoh paling jelas: halaman profil user di aplikasi sosial menampilkan nama, email, bio, dan jumlah follower secara bersamaan. Di RDBMS, itu bisa berarti menggabungkan tiga tabel. Di MongoDB, simpan semuanya dalam satu dokumen:

Satu dokumen menyimpan semua data yang dibaca bersama
{
  "_id": ObjectId("66xxxxxxxxxxxxxxxxxxxxxxxx"),
  "username": "arman",
  "email": "arman@example.com",
  "bio": "Cloud engineer dan pembelajar seumur hidup",
  "followerCount": 1280,
  "profile": {
    "location": "Jakarta",
    "website": "https://arman.dev"
  }
}

Satu query find mengambil seluruh data yang dibutuhkan untuk halaman profil. Tidak ada JOIN, tidak ada query kedua. Inilah keunggulan performa utama document database.

Trade-off Duplikasi Data

Data locality biasanya berarti menduplikasi data di beberapa tempat. Misalnya nama user di-duplikasi ke setiap dokumen order yang pernah dibuatnya. Duplikasi ini disengaja — ia menukar konsistensi pembaruan (harus di-update di banyak tempat) dengan kecepatan baca. Kita akan membedah embedding vs referencing secara mendalam di episode 7; untuk sekarang, ingat prinsipnya: tempatkan data berdasarkan cara data itu dibaca, bukan berdasarkan teori normalisasi.

Access Pattern: Desain Schema Berorientasi Query

Schema MongoDB yang baik tidak dirancang dari sisi entitas ("user punya apa saja?"), melainkan dari sisi query ("query apa yang paling sering jalan?"). Mulailah dengan menuliskan daftar query yang akan paling sering dieksekusi aplikasi kalian, lalu rancang dokumen agar setiap query utama bisa diselesaikan dengan membaca sesedikit mungkin dokumen.

Langkah praktisnya:

  1. Tulis 10 query paling sering dipakai aplikasi kalian.
  2. Identifikasi field yang diakses di setiap query.
  3. Kelompokkan field yang selalu muncul bersama.
  4. Susun dokumen sehingga satu query terpenting = satu dokumen terbaca.
Melihat pola akses dari query yang sering dipakai
db.orders.find({ userId: ObjectId("66xxxxxxxxxxxxxxxxxxxxxxxx") })

Query di atas sangat umum: "tampilkan semua order user ini". Jika userId tidak ber-index, setiap eksekusi menjadi full scan. Memahami access pattern seperti ini akan memandu kalian menempatkan field dan memilih index — topik yang kita lanjutkan di episode 12.

Anti-Pattern yang Harus Dihindari

Massive Arrays (Unbounded Growth)

Anti-pattern pertama: array yang tumbuh tanpa batas. Contoh paling umum: menyimpan semua komentar produk di dalam dokumen produk. Produk viral bisa mendapat puluhan ribu komentar, dan tiap operasi yang menyentuh dokumen produk harus memuat seluruh array itu — lambat dan boros memory.

Anti-pattern: array komentar tak terbatas di dalam dokumen produk
{
  "_id": ObjectId("66xxxxxxxxxxxxxxxxxxxxxxxx"),
  "name": "Laptop Gaming",
  "comments": [
    { "user": "budi", "text": "Keren!" },
    { "user": "siti", "text": "Harga oke" }
  ]
}

Solusinya: pisahkan komentar ke collection terpisah dengan referensi ke produk. Array dalam dokumen sebaiknya dibatasi untuk relasi "one-to-few" — beberapa lusin elemen maksimal, bukan ribuan.

Excessive Nesting (Terlalu Dalam)

Anti-pattern kedua: embedding yang terlalu dalam dan lebar. Dokumen bersarang lebih dari tiga level menjadi sulit dibaca, sulit di-index, dan sulit di-query. Nested document yang kompleks membuat path query seperti profile.address.history.locations[...] terasa menyakitkan.

Anti-pattern: nesting melebihi 3 level
{
  "user": {
    "account": {
      "settings": {
        "notifications": {
          "email": {
            "marketing": true
          }
        }
      }
    }
  }
}

Solusinya: flat-kan struktur. Batasi kedalaman maksimal 3 level, dan untuk data yang benar-benar hierarkis (kategori, organisasi), pertimbangkan pola seperti array ancestors atau collection terpisah.

Over-Normalized Schema ala RDBMS

Anti-pattern ketiga: membawa kebiasaan RDBMS — memecah setiap entitas kecil-kecil ke collection terpisah lalu menyambungnya dengan $lookup di setiap query. Ini membuang seluruh keunggulan document database. Indikatornya: query kalian selalu diawali banyak $lookup, dan setiap pembacaan data butuh puluhan dokumen digabung.

Solusinya bukan normalisasi penuh atau denormalisasi penuh, tapi pendekatan hybrid yang kita bahas di episode 7: embed data yang dibaca bersama, referensikan data yang besar atau sering berubah sendiri.

Info

Ada kerangka berpikir cepat untuk memutuskan: tanyakan "apakah data ini selalu dibaca bersama dengan dokumen induk?" Jika ya dan jumlahnya sedikit, embed. Jika tidak, atau jumlahnya besar, referensikan. Keputusan ini jarang hitam-putih — itulah mengapa MongoDB memberi kalian kebebasan memilih, dan mengapa kalian harus memilih dengan sadar.

Penutup

Pada episode 6 ini kalian telah memahami bahwa flexible schema justru menuntut desain yang lebih disiplin, menguasai prinsip utama data locality — data yang diakses bersama disimpan bersama — dan belajar merancang schema berorientasi access pattern, yaitu menyusun dokumen berdasarkan query yang paling sering dieksekusi. Kalian juga mengenali tiga anti-pattern utama: massive arrays yang tumbuh tak terkendali, excessive nesting melebihi tiga level, dan over-normalized schema yang membawa kebiasaan RDBMS ke MongoDB.

Inti yang harus dibawa pulang:

  • Schemaless berarti desain jadi tanggung jawab kalian, bukan berarti tanpa desain.
  • Data locality adalah prinsip nomor satu: simpan data yang dibaca bersama dalam satu dokumen.
  • Rancang schema dari daftar query, bukan dari daftar entitas.
  • Array dalam dokumen cocok untuk one-to-few; pisahkan yang pertumbuhannya besar.
  • Batasi kedalaman embedding maksimal 3 level.

Di episode 7 berikutnya kita membedah salah satu keputusan terpenting dalam desain: Data Modeling: Embedding vs Referencing. Kalian akan mempelajari kapan meng-embed dokumen, kapan mereferensikan dengan ObjectId, pola one-to-few, one-to-many, dan many-to-many, serta pendekatan hybrid yang menggabungkan keduanya. Sampai jumpa di episode 7!

Belajar MongoDB - Schema Design Patterns & Best Practices | Belajar MongoDB