Faktisk er den "bedste" måde at gøre dette på snarere at bruge .aggregate()
og $lookup
at "join" dataene og "filtrere" på matchbetingelserne. Dette er meget effektivt, da MongoDB faktisk udfører alt dette på selve "serveren" sammenlignet med at udstede "flere" forespørgsler som .populate()
gør.
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}}
])
Hvis der er "masser" af placeringer, så er det bedst at bruge $unwind
, som vil oprette et dokument for hvert relateret "rangering"-element:
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}},
{ "$unwind": "$rankings" }
])
Der er også en særlig håndtering her af, hvordan MongoDB håndterer "tilslutning" af dokumenter for at undgå at bryde 16MB BSON-grænsen. Så faktisk sker denne specielle ting, når $unwind
følger direkte en $lookup
pipeline fase:
{
"$lookup" : {
"from" : "rankmovies",
"as" : "rankings",
"localField" : "_id",
"foreignField" : "movie",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
}
}
}
Så $unwind
faktisk "forsvinder" og i stedet "rulles op" i
Hvis du ikke har en MongoDB, der understøtter $lookup
( MongoDB 3.2 minunum ) så kunne du bruge en "virtuel" med .populate()
i stedet (kræver minimum Mongoose 4.5.0 ). Men bemærk, at dette faktisk udfører "to" forespørgsler til serveren:
Tilføj først det "virtuelle" til skemaet:
movieSchema.virtual("rankings",{
"ref": "Movie",
"localField": "_id",
"foreignField": "movie"
});
Udsend derefter forespørgslen med .populate()
:
MovieModel.find({ "m_title": m_title })
.populate('rankings')
.exec()