Na verdade, a "melhor" maneira de fazer isso é usar
.aggregate()
e $lookup
para "juntar" os dados e "filtrar" nas condições de jogo. Isso é muito eficaz, pois o MongoDB realmente executa tudo isso no próprio "servidor", em comparação com a emissão de consultas "múltiplas" como .populate()
faz. MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}}
])
Se houver "muitos" rankings, é melhor usar
$unwind
, que criará um documento para cada item de "classificação" relacionado:MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}},
{ "$unwind": "$rankings" }
])
Há também um tratamento especial aqui de como o MongoDB lida com documentos de "junção" para evitar violar o limite de 16 MB de BSON. Então, na verdade, essa coisa especial acontece quando
$unwind
segue diretamente um $lookup
estágio do encanamento: {
"$lookup" : {
"from" : "rankmovies",
"as" : "rankings",
"localField" : "_id",
"foreignField" : "movie",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
}
}
}
Portanto, o
$unwind
na verdade "desaparece" e, em vez disso, é "enrolado" no $pesquisa
si mesmo como se isso fosse "uma" operação. Dessa forma, não criamos um "array" diretamente no documento pai, o que faria com que o tamanho excedesse 16 MB em casos extremos com muitos itens "relacionados". Se você não tiver um MongoDB que suporte
$lookup
( MongoDB 3.2 minunum ), então você pode usar um "virtual" com .populate()
em vez disso (requer Mongoose 4.5.0 mínimo ). Mas observe que isso realmente executa "dois" consultas ao servidor:Primeiro adicione o "virtual" ao esquema:
movieSchema.virtual("rankings",{
"ref": "Movie",
"localField": "_id",
"foreignField": "movie"
});
Em seguida, emita a consulta com
.populate()
:MovieModel.find({ "m_title": m_title })
.populate('rankings')
.exec()