Hal pertama yang harus dipahami tentang populasi luwak adalah bahwa ini bukan sihir, tetapi hanya metode praktis yang memungkinkan Anda mengambil informasi terkait tanpa melakukan semuanya sendiri.
Konsep ini pada dasarnya untuk digunakan di mana Anda memutuskan Anda akan perlu menempatkan data dalam koleksi terpisah daripada menyematkan data itu, dan pertimbangan utama Anda harus biasanya pada ukuran dokumen atau di mana informasi terkait sering diperbarui yang akan membuat mempertahankan data yang disematkan dengan susah payah.
Bagian "tidak ajaib" adalah bahwa pada dasarnya apa yang terjadi di bawah selimut adalah ketika Anda "mengacu" sumber lain, fungsi populate membuat kueri/kueri tambahan ke koleksi "terkait" itu untuk "menggabungkan" hasil induk tersebut objek yang telah Anda ambil. Anda dapat melakukannya sendiri, tetapi ada metode yang memudahkan untuk menyederhanakan tugas. Pertimbangan "kinerja" yang jelas adalah bahwa tidak ada satu perjalanan pulang pergi ke database (instance MongoDB) untuk mengambil semua informasi. Selalu ada lebih dari satu.
Sebagai sampel, ambil dua koleksi:
{
"_id": ObjectId("5392fea00ff066b7d533a765"),
"customerName": "Bill",
"items": [
ObjectId("5392fee10ff066b7d533a766"),
ObjectId("5392fefe0ff066b7d533a767")
]
}
Dan itemnya:
{ "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 }
{ "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 }
Yang "terbaik" yang dapat dilakukan oleh model "referensi" atau penggunaan populate (under the hood) adalah ini:
var order = db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") });
order.items = db.items.find({ "_id": { "$in": order.items } ).toArray();
Jadi jelas ada "setidaknya" dua kueri dan operasi untuk "menggabungkan" data itu.
Konsep embedding pada dasarnya adalah jawaban MongoDB untuk bagaimana menangani tidak mendukung "bergabung". Jadi alih-alih membagi data menjadi koleksi yang dinormalisasi, Anda mencoba menyematkan data "terkait" langsung di dalam dokumen yang menggunakannya. Keuntungannya di sini adalah ada satu operasi "baca" untuk mengambil informasi "terkait", dan juga satu titik operasi "tulis" untuk memperbarui entri "induk" dan "anak", meskipun seringkali tidak mungkin untuk menulis ke "banyak" anak sekaligus tanpa memproses "daftar" pada klien atau menerima operasi tulis "banyak", dan lebih disukai dalam pemrosesan "batch".
Data kemudian lebih terlihat seperti ini (dibandingkan dengan contoh di atas):
{
"_id": ObjectId("5392fea00ff066b7d533a765"),
"customerName": "Bill",
"items": [
{ "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 },
{ "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 }
]
}
Oleh karena itu, sebenarnya pengambilan data hanyalah masalah:
db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") });
Pro dan kontra dari keduanya akan selalu sangat bergantung pada pola penggunaan aplikasi Anda. Tapi sekilas:
Menyematkan
-
Ukuran total dokumen dengan data yang disematkan biasanya tidak akan melebihi penyimpanan 16 MB (batas BSON) atau sebaliknya ( sebagai pedoman ) memiliki larik yang berisi 500 entri atau lebih.
-
Data yang disematkan umumnya tidak memerlukan perubahan yang sering. Jadi Anda bisa hidup dengan "duplikasi" yang berasal dari de-normalisasi yang tidak mengakibatkan kebutuhan untuk memperbarui "duplikat" tersebut dengan informasi yang sama di banyak dokumen induk hanya untuk meminta perubahan.
-
Data terkait sering digunakan dalam hubungan dengan orang tua. Artinya, jika kasus "baca/tulis" Anda hampir selalu perlu "membaca/menulis" ke induk dan anak, maka masuk akal untuk menyematkan data untuk operasi atom.
Mereferensi
-
Data terkait akan selalu melebihi batas BSON 16MB. Anda selalu dapat mempertimbangkan pendekatan hibrida "bucketing", tetapi batas keras umum dari dokumen utama tidak dapat dilanggar. Kasus umum adalah "posting" dan "komentar" di mana aktivitas "komentar" diperkirakan akan sangat besar.
-
Data terkait perlu diperbarui secara berkala. Atau pada dasarnya kasus di mana Anda "menormalkan" karena data itu "dibagikan" di antara banyak orang tua dan data "terkait" cukup sering diubah sehingga tidak praktis untuk memperbarui item yang disematkan di setiap "induk" tempat item "anak" itu muncul . Kasus yang lebih mudah adalah dengan mereferensikan "anak" dan membuat perubahan sekali.
-
Ada pemisahan yang jelas antara membaca dan menulis. Dalam kasus di mana mungkin Anda tidak akan selalu memerlukan informasi "terkait" saat membaca "induk" atau sebaliknya tidak perlu selalu mengubah "induk" saat menulis kepada anak, mungkin ada alasan bagus untuk memisahkan model seperti yang dirujuk. Selain itu jika ada keinginan umum untuk memperbarui banyak "sub-dokumen" sekaligus di mana "sub-dokumen" itu sebenarnya adalah referensi ke koleksi lain, maka seringkali implementasinya lebih efisien dilakukan ketika data berada di tempat yang terpisah. koleksi.
Jadi sebenarnya ada diskusi yang lebih luas tentang "pro/kontra" untuk kedua posisi pada dokumentasi MongoDB tentang Pemodelan Data, yang mencakup berbagai kasus penggunaan dan cara pendekatan baik menggunakan penyematan atau model yang direferensikan seperti yang didukung oleh metode populasi.
Semoga "titik titik" berguna, tetapi rekomendasi umumnya adalah mempertimbangkan pola penggunaan data aplikasi Anda dan memilih yang terbaik. Memiliki "opsi" untuk menyematkan "seharusnya" menjadi alasan Anda memilih MongoDB, tetapi sebenarnya bagaimana aplikasi Anda "menggunakan data" yang membuat keputusan metode mana yang sesuai dengan bagian mana dari pemodelan data Anda (karena tidak "semua atau tidak sama sekali") yang terbaik.
- Perhatikan bahwa sejak ini awalnya ditulis, MongoDB memperkenalkan
$lookup
operator yang memang melakukan "gabungan" antar koleksi di server. Untuk tujuan diskusi umum di sini, yang "lebih baik" di sebagian besar keadaan bahwa overhead "beberapa kueri" yang dikeluarkan olehpopulate()
dan "beberapa kueri" secara umum, masih ada "overhead yang signifikan" terjadi dengan$lookup
operasi.Prinsip desain inti adalah "tertanam" berarti "sudah ada" sebagai lawan dari "mengambil dari tempat lain". Pada dasarnya perbedaan antara "di saku Anda" dan "di rak", dan dalam istilah I/O biasanya lebih seperti "di rak di perpustakaan pusat kota" , dan terutama lebih jauh untuk permintaan berbasis jaringan.