Eigentlich ist der "beste" Weg, dies zu tun, eher die Verwendung von .aggregate()
und $lookup
um die Daten zu "verknüpfen" und nach den Spielbedingungen zu "filtern". Dies ist sehr effektiv, da MongoDB all dies tatsächlich auf dem "Server" selbst durchführt, im Vergleich zur Ausgabe "mehrerer" Abfragen als .populate()
tut.
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}}
])
Wenn es „viele“ Rankings gibt, verwenden Sie am besten $unwind
, wodurch ein Dokument für jedes zugehörige "Ranking"-Element erstellt wird:
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}},
{ "$unwind": "$rankings" }
])
Hier gibt es auch eine spezielle Handhabung, wie MongoDB mit dem „Zusammenführen“ von Dokumenten umgeht, um ein Überschreiten der 16-MB-BSON-Grenze zu vermeiden. Tatsächlich passiert also diese besondere Sache, wenn $unwind
folgt direkt auf $lookup
Pipeline-Phase:
{
"$lookup" : {
"from" : "rankmovies",
"as" : "rankings",
"localField" : "_id",
"foreignField" : "movie",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
}
}
}
Also der $unwind
tatsächlich "verschwindet" und stattdessen in den <-Code "aufgerollt" wird>$nachschlagen
als wäre dies "eine" Operation. Auf diese Weise erstellen wir kein "Array" direkt im übergeordneten Dokument, das bei vielen "verwandten" Elementen im Extremfall die Größe von 16 MB überschreiten würde.
Wenn Sie keine MongoDB haben, die $lookup
(MongoDB mindestens 3.2 ), dann könnten Sie ein "virtuelles" mit .populate()
verwenden
stattdessen (erfordert mindestens Mongoose 4.5.0 ). Beachten Sie jedoch, dass dies tatsächlich "zwei" ausführt Anfragen an den Server:
Fügen Sie zuerst das "virtuelle" zum Schema hinzu:
movieSchema.virtual("rankings",{
"ref": "Movie",
"localField": "_id",
"foreignField": "movie"
});
Setzen Sie dann die Abfrage mit .populate()
ab
:
MovieModel.find({ "m_title": m_title })
.populate('rankings')
.exec()