Всъщност „най-добрият“ начин да направите това е по-скоро да използвате .aggregate()
и $lookup
за „обединяване“ на данните и „филтриране“ по условията на съвпадение. Това е много ефективно, тъй като MongoDB всъщност изпълнява всичко това на самия "сървър", в сравнение с издаването на "множество" заявки като .populate()
прави.
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}}
])
Ако има „много“ класации, най-добре е да използвате $unwind
, което ще създаде документ за всеки свързан елемент с „класиране“:
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}},
{ "$unwind": "$rankings" }
])
Тук също има специална обработка на начина, по който MongoDB се справя с „съединяването“ на документи, за да се избегне нарушаване на ограничението от 16MB BSON. Така че всъщност това специално нещо се случва, когато $unwind
директно следва $lookup
етап на тръбопровод:
{
"$lookup" : {
"from" : "rankmovies",
"as" : "rankings",
"localField" : "_id",
"foreignField" : "movie",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
}
}
}
Така че $unwind
всъщност „изчезва“ и вместо това е „навит“ в $lookup
като че ли това е "една" операция. По този начин ние не създаваме "масив" директно в родителския документ, което би довело до надвишаване на размера от 16 MB в крайни случаи с много "свързани" елементи.
Ако нямате MongoDB, която поддържа $lookupкод>
( MongoDB 3.2 мин. ), тогава можете да използвате „виртуален“ с .populate()
вместо това (изисква минимум Mongoose 4.5.0 ). Но имайте предвид, че това всъщност изпълнява "две" заявки към сървъра:
Първо добавете „виртуалния“ към схемата:
movieSchema.virtual("rankings",{
"ref": "Movie",
"localField": "_id",
"foreignField": "movie"
});
След това подайте заявката с .populate()
:
MovieModel.find({ "m_title": m_title })
.populate('rankings')
.exec()