Właściwie „najlepszym” sposobem na to jest użycie .aggregate()
i $lookup
aby „dołączyć” dane i „filtrować” warunki dopasowania. Jest to bardzo skuteczne, ponieważ MongoDB faktycznie wykonuje to wszystko na samym „serwerze”, w porównaniu do wysyłania „wielu” zapytań jako .populate()
tak.
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}}
])
Jeśli istnieje „dużo” rankingów, najlepiej użyć $rozwiń
, który utworzy dokument dla każdego powiązanego elementu „rankingu”:
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}},
{ "$unwind": "$rankings" }
])
Istnieje również specjalna obsługa tego, jak MongoDB radzi sobie z „łączeniem” dokumentów, aby uniknąć przekroczenia limitu 16 MB BSON. Tak więc w rzeczywistości ta wyjątkowa rzecz ma miejsce, gdy $unwind
bezpośrednio podąża za $lookup
etap potoku:
{
"$lookup" : {
"from" : "rankmovies",
"as" : "rankings",
"localField" : "_id",
"foreignField" : "movie",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
}
}
}
Tak więc $unwind
faktycznie „znika”, a zamiast tego jest „zwijany” do $wyszukaj
się tak, jakby to była „jedna” operacja. W ten sposób nie tworzymy „tablicy” bezpośrednio w dokumencie nadrzędnym, która w skrajnych przypadkach spowodowałaby przekroczenie 16 MB przy wielu „powiązanych” elementach.
Jeśli nie masz bazy danych MongoDB, która obsługuje $lookup
( MongoDB 3,2 minunum ), możesz użyć „wirtualnego” z .populate()
zamiast tego (wymaga minimum 4.5.0 Mongoose ). Pamiętaj jednak, że w rzeczywistości działa to „dwa” zapytania do serwera:
Najpierw dodaj „wirtualny” do schematu:
movieSchema.virtual("rankings",{
"ref": "Movie",
"localField": "_id",
"foreignField": "movie"
});
Następnie wyślij zapytanie za pomocą .populate()
:
MovieModel.find({ "m_title": m_title })
.populate('rankings')
.exec()