{count, plural, one {Kursus} other {Kursus}}
Jadi Anda ingin membangun sistem manajemen konten (CMS) Anda sendiri, yang kadang juga disebut blog? Ini adalah contoh klasik saat belajar menggunakan basis data, baik itu sistem manajemen basis data relasional (RDBMS) maupun basis data NoSQL, karena mencakup potensi data berjumlah besar serta relasi di dalamnya. Contoh aplikasi blog juga mudah diterapkan untuk kebutuhan pemodelan data lainnya.
Pada artikel ini, kita akan membahas beberapa hal yang sebaiknya dilakukan dan dihindari ketika merancang dokumen NoSQL di MongoDB. Namun, kita tidak akan benar-benar membuat aplikasi blog, melainkan melihatnya dari sudut pandang data.
Komponen-Komponen dalam Aplikasi Blog
Sebelum mencoba merancang model dokumen untuk blog, ada baiknya mundur selangkah dan memikirkan setiap komponen yang mungkin memiliki data terkait.
Sebuah blog tipikal mungkin memiliki fitur-fitur berikut:
- Banyak pengguna atau penulis
- Banyak postingan blog untuk setiap penulis
- Banyak komentar untuk setiap postingan blog
Tentu saja, daftar fitur tersebut bisa menjadi lebih panjang dan kompleks tergantung kebutuhan bisnis blog Anda. Untuk menyederhanakan, kita akan memodelkan data berdasarkan hal-hal di atas.
Hal yang Bisa Dilakukan, Namun Sebaiknya Tidak
Pikiran pertama Anda saat melihat fitur-fitur di atas mungkin adalah memperlakukan setiap butir sebagai dokumen tersendiri. Ini adalah pendekatan tipikal di basis data relasional seperti Postgres. Di MongoDB, ini mungkin terlihat seperti berikut:
{
"_id": "author-1",
"name": "Nic Raboy",
"description": "I'm some dude named Nic."
}
Contoh di atas adalah representasi penulis yang sangat disederhanakan. Tentu Anda bisa menambahkan banyak kolom lain, seperti email dan sebagainya, tetapi itu tidak terlalu penting di sini.
Lalu, kita bisa memiliki dokumen berikut untuk postingan blog:
{
"_id": "blog-1",
"author_id": "author-1",
"title": "MongoDB is Awesome!",
"content": "This is some blog content..."
}
Sama seperti sebelumnya, dokumen blog bisa memiliki kolom lain seperti tags dan apa pun yang Anda pikirkan. Hal terpenting di sini adalah adanya referensi id antara dua dokumen tersebut. Namun, kita akan bahas itu sebentar lagi.
Model dokumen terakhir dalam skenario ini adalah untuk komentar:
{
"_id": "comment-1",
"blog_id": "blog-1",
"username": "Anonymous User",
"content": "Hey great article, it really helped a lot!"
}
Sekali lagi, dokumen komentar dalam skenario ini memiliki relasi referensi berdasarkan nilai id antara dokumen komentar dan dokumen blog. Ini sangat umum di basis data relasional, dan kenyataannya akan berfungsi dengan baik di MongoDB juga. Namun, ini tidak akan memberi Anda pengalaman terbaik di MongoDB.
Salah satu alasan Anda tidak ingin melakukan ini di MongoDB adalah karena kinerja.
Untuk menggabungkan ketiga dokumen ini, Anda perlu menggunakan operasi $lookup dalam pipeline agregasi. Operasi $lookup tidak murah dan dapat berdampak negatif pada kinerja saat basis data Anda berkembang, terlebih lagi jika Anda memiliki lebih dari satu operasi $lookup dalam pipeline Anda.
Ada cara yang lebih baik untuk menyelesaikan tugas ini di MongoDB.
Pendekatan Pemodelan Data yang Lebih Baik dan Lebih Ramah MongoDB
Salah satu aturan pertama di MongoDB adalah data yang diakses bersama sebaiknya disimpan bersama. Menyimpan setiap fitur dalam dokumen atau koleksi terpisah melanggar aturan tersebut karena kita tidak lagi melakukan operasi pengambilan tunggal untuk data yang ditampilkan kepada pengguna.
Mari kita coba lagi, dengan memodelkan dokumen untuk blog kita seperti ini:
{
"_id": "author-1",
"name": "Nic Raboy",
"description": "I'm some dude named Nic.",
"posts": [
{
"title": "MongoDB is Awesome!",
"content": "This is some blog content...",
"comments": [
{
"username": "Anonymous User",
"content": "Hey great article, it really helped a lot!"
}
]
}
]
}
Baik, jadi salah satu aturan utama MongoDB terpenuhi pada model di atas. Kita memiliki satu dokumen yang menggunakan nesting untuk menyimpan semua postingan blog dan semua komentar bersama penulisnya.
Meskipun bisa berfungsi, mungkin bukan ide yang baik untuk memodelkan dokumen aplikasi blog Anda seperti itu.
MongoDB memiliki batas ukuran dokumen, dan ketika Anda memiliki array yang tidak dibatasi dalam dokumen, Anda berisiko melampaui batas tersebut. Belum lagi Anda mungkin menghadapi masalah kinerja saat array menjadi besar. Dalam kasus ini, kita bisa memiliki jumlah postingan blog tak terbatas dan jumlah komentar tak terbatas per postingan. Pada titik tertentu, ini akan menjadi berantakan.
Yang mungkin lebih baik dalam contoh ini adalah memadukan kedua strategi.
Ingat, penulis, postingan blog, dan komentar bisa memiliki banyak kolom terkait. Pada contoh ini, kita menjaganya minimal. Dengan itu, kita tahu bahwa data yang paling sering diakses adalah blog itu sendiri. Perhatikan desain baru berikut:
{
"_id": "blog-1",
"author": {
"_id": "author-1",
"name": "Nic Raboy",
},
"title": "MongoDB is Awesome!",
"content": "This is some blog content...",
"comments": [
{
"username": "Anonymous User",
"content": "Hey great article, it really helped a lot!"
}
]
}
Dokumen kedua dalam contoh ini tetap merupakan dokumen asli untuk informasi penulis:
{
"_id": "author-1",
"name": "Nic Raboy",
"description": "I'm some dude named Nic."
}
Kita tahu bahwa sebagian informasi penulis perlu disertakan saat menampilkan artikel blog, namun tidak semua informasi harus ditampilkan. Kita dapat menyematkan informasi penulis yang dibutuhkan beserta _id di dalam postingan blog, dan jika pengguna ingin mengetahui lebih lanjut tentang penulis, pengguna dapat menelusuri lebih jauh di aplikasi Anda. Operasi $lookup tidak terjadi setiap saat, sehingga meningkatkan kinerja.
Sekarang, kita memiliki masalah potensi jumlah komentar yang tak terbatas untuk setiap artikel blog yang saat ini terlampir sebagai array.
Ada beberapa pendekatan untuk menangani ini dan pada akhirnya terserah Anda:
- Anda bisa melakukan pendekatan naif dan menyimpannya sebagai array, yang mungkin bukan ide yang bagus.
- Anda bisa memindahkan komentar kembali ke desain awal, yaitu satu komentar per dokumen yang semuanya memiliki id referensi ke artikel blog dan menggunakan operasi
$lookupuntuk menyertakannya. - Anda bisa menggunakan strategi pengarsipan, menyimpan sejumlah tetap komentar dalam array di dalam artikel blog sekaligus membuat dokumen komentar terpisah untuk masing-masing, sehingga Anda hanya perlu melakukan query untuk komentar tambahan jika diperlukan.
- Anda bisa mengeksplorasi pola bucketing, yaitu mengelompokkan komentar ke dalam "bucket" sekitar 100 komentar per dokumen, lalu melakukan query sebanyak bucket komentar yang Anda perlukan pada suatu waktu. Bucketing menghindari batas ukuran dokumen dan juga membantu dengan paginasi. Anda juga bisa meningkatkan kinerja dalam pendekatan ini dengan membuat indeks pada
blog_iduntuk dengan cepat mengambil komentar untuk artikel blog tertentu. Informasi lebih lanjut tentang pengindeksan dapat ditemukan di dokumentasi MongoDB. - Campur, padukan, dan seterusnya...
Dalam kasus pola bucketing, dokumen komentar Anda mungkin terlihat seperti berikut:
{
"_id": "comment-bucket-1",
"blog_id": "blog-1",
"comments": [
{
"username": "Anonymous User",
"content": "Hey great article, it really helped a lot!"
},
// More comments here...
],
"comment_count": 57
}
Dalam skenario ini, saat komentar baru dibuat, Anda melakukan query untuk bucket yang belum penuh. Anda menambahkan komentar baru ke array dan menaikkan nilai hitungan. Meskipun strategi ini lebih bergantung pada logika tingkat aplikasi untuk memelihara bucket, hasilnya kinerja yang lebih baik. Jika Anda memiliki mekanisme gulir tanpa batas di blog, malah lebih baik karena Anda bisa melakukan paginasi dengan lebih baik menggunakan bucket.
Meskipun di luar cakupan artikel ini, jika Anda ingin merasakan seperti apa proses menambahkan komentar baru, Anda akan memfilter koleksi bucket komentar (lihat contoh query di bawah) untuk bucket yang cocok dengan blog_id serta memiliki comment_count kurang dari nilai yang Anda pilih.
Untuk pencocokan tersebut, Anda akan menggunakan operator $push dalam kriteria pembaruan dan operator $inc untuk meningkatkan nilai hitungan komentar. Semua ini bisa dilakukan dalam satu operasi, dan jika Anda menggunakan flag upsert, Anda dapat membuat bucket komentar baru jika belum ada yang sesuai dengan kriteria Anda.
Contoh query pembaruan:
db.commentBuckets.updateOne(
{ blog_id: "blog-1", comment_count: { $lt: 100 } },
{ $push: { comments: newComment }, $inc: { comment_count: 1 } },
{ upsert: true }
)
Kesimpulan
Sebagus apa pun kedengarannya untuk menyimpan semua hal tentang blog Anda dalam satu dokumen bertingkat, kemungkinan besar itu bukan ide yang baik. Sama seperti kemungkinan besar bukan ide yang baik untuk menerapkan model data yang cocok untuk basis data relasional, tetapi tidak untuk basis data dokumen seperti MongoDB.
Dengan MongoDB, Anda ingin mengurangi relasi referensi sebanyak mungkin untuk mendapatkan kinerja terbaik.
Perhatikan hal-hal berikut saat Anda melakukan skala:
- Jika Anda memperkirakan jumlah komentar yang tinggi, pertimbangkan pola bucket atau kombinasinya bersama embedding parsial di dokumen blog.
- Apa kebutuhan paginasi Anda?
- Indeks koleksi Anda berdasarkan cara Anda berencana melakukan query di aplikasi.
Sebagai pengingat, pikirkan bagaimana Anda akan menyajikan data blog di frontend. Apakah Anda benar-benar membutuhkan semua informasi penulis dalam permintaan atau sebagian saja sudah cukup? Apakah Anda benar-benar ingin memuat satu juta komentar bersama artikel blog atau cukup memuat beberapa saja? Jika Anda benar-benar memikirkannya, Anda akan terkejut berapa banyak operasi join yang sebenarnya tidak Anda perlukan.
Jika Anda baru mengenal MongoDB, saya sarankan melihat kursus Pengantar MongoDB di Python.
FAQ
Bisakah saya memindahkan model data aplikasi blog saya dari basis data relasional ke MongoDB?
Anda dapat membuat dokumen datar dengan referensi id dan itu akan berfungsi, namun Anda tidak memanfaatkan kinerja maksimum yang bisa didapatkan dengan MongoDB.
Mengapa tidak menyimpan semuanya dalam satu dokumen saja?
Ada batas ukuran di MongoDB dan ketika Anda memiliki array yang tidak dibatasi, Anda bisa dengan mudah mencapai batas tersebut.
Pola bucket disebutkan, tetapi apakah ada pola lain?
Ada pola lain yang mungkin cocok, tetapi pola bucket adalah opsi yang baik saat berurusan dengan array besar.
Berapa batas ukuran dokumen MongoDB?
Dokumen MongoDB memiliki ukuran maksimum 16MB.
Bagaimana cara menangani pembaruan data bertingkat (misalnya, mengedit komentar)?
Untuk data tertanam, Anda dapat menggunakan operator pembaruan seperti $set, dan untuk komentar yang dibucket, Anda dapat menemukan bucket dan memperbarui komentar spesifik di dalamnya.

Nic Raboy adalah Pimpinan Developer Relations di MongoDB, memimpin tim pengembang Python, Java, C#, dan PHP yang membuat konten luar biasa untuk membantu para pengembang berhasil mengintegrasikan MongoDB ke dalam proyek mereka. Ia berpengalaman dengan Golang dan JavaScript dan sering menulis tentang berbagai petualangan pengembangannya.
