Sebenarnya cara "terbaik" untuk melakukan ini adalah menggunakan .aggregate()
dan $lookup
untuk "bergabung" dengan data dan "filter" pada kondisi kecocokan. Ini sangat efektif karena MongoDB benar-benar melakukan semua ini di "server" itu sendiri, dibandingkan dengan mengeluarkan "beberapa" kueri sebagai .populate()
tidak.
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}}
])
Jika ada "banyak" peringkat, sebaiknya gunakan $unwind
, yang akan membuat dokumen untuk setiap item "peringkat" terkait:
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}},
{ "$unwind": "$rankings" }
])
Ada juga penanganan khusus di sini tentang bagaimana MongoDB menangani dokumen "bergabung" untuk menghindari pelanggaran batas BSON 16MB. Jadi sebenarnya hal istimewa ini terjadi ketika $unwind
langsung mengikuti $lookup
tahap saluran:
{
"$lookup" : {
"from" : "rankmovies",
"as" : "rankings",
"localField" : "_id",
"foreignField" : "movie",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
}
}
}
Jadi $unwind
sebenarnya "menghilang" dan sebaliknya "digulung" ke $lookup
sendiri seolah-olah ini adalah operasi "satu". Dengan cara itu kami tidak membuat "array" langsung di dalam dokumen induk yang akan menyebabkan ukuran melebihi 16MB dalam kasus ekstrim dengan banyak item "terkait".
Jika Anda tidak memiliki MongoDB yang mendukung $lookup
( MongoDB 3.2 minunum ) maka Anda dapat menggunakan "virtual" dengan .populate()
sebagai gantinya (membutuhkan minimum Mongoose 4.5.0 ). Namun perhatikan bahwa ini sebenarnya menjalankan "dua" kueri ke server:
Pertama tambahkan "virtual" ke skema:
movieSchema.virtual("rankings",{
"ref": "Movie",
"localField": "_id",
"foreignField": "movie"
});
Kemudian keluarkan kueri dengan .populate()
:
MovieModel.find({ "m_title": m_title })
.populate('rankings')
.exec()