Ve skutečnosti je „nejlepší“ způsob, jak toho dosáhnout, spíše pomocí .aggregate()
a $lookup
"spojit" data a "filtrovat" podmínky zápasu. To je velmi efektivní, protože MongoDB to všechno ve skutečnosti provádí na „serveru“ samotném, ve srovnání s vydáváním „více“ dotazů jako .populate()
ano.
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}}
])
Pokud existuje "spousta" hodnocení, pak je nejlepší použít $unwind
, který vytvoří dokument pro každou související položku "žebříčku":
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}},
{ "$unwind": "$rankings" }
])
Je zde také speciální zpracování toho, jak MongoDB řeší „spojování“ dokumentů, aby nedošlo k překročení limitu 16 MB BSON. Takže ve skutečnosti se tato zvláštní věc stane, když $unwind
přímo navazuje na $lookup
fáze potrubí:
{
"$lookup" : {
"from" : "rankmovies",
"as" : "rankings",
"localField" : "_id",
"foreignField" : "movie",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
}
}
}
Takže $unwind
ve skutečnosti „zmizí“ a místo toho je „srolován“ do $lookup
jako by to byla „jedna“ operace. Tímto způsobem nevytváříme "pole" přímo v nadřazeném dokumentu, což by u mnoha "souvisejících" položek v extrémních případech způsobilo překročení velikosti 16 MB.
Pokud nemáte MongoDB, který podporuje $lookup
( MongoDB 3.2 minunum ), pak byste mohli použít "virtuální" s .populate()
místo toho (vyžaduje minimálně Mongoose 4.5.0 ). Ale všimněte si, že to ve skutečnosti provádí "dva" dotazy na server:
Nejprve přidejte „virtuální“ do schématu:
movieSchema.virtual("rankings",{
"ref": "Movie",
"localField": "_id",
"foreignField": "movie"
});
Poté zadejte dotaz pomocí .populate()
:
MovieModel.find({ "m_title": m_title })
.populate('rankings')
.exec()