MongoDB: агрегація, populate vs lookup
Агрегация (aggregate) - это выполнение сложных поисковых запросов.
Например, у нас есть коллекция пользователей со следующими документами:
userModel.create(
{ "_id" : 1, "name" : "Ivan", "favouriteFilmIds" : [1,3,5] },
{ "_id" : 2, "name" : "Igor", "favouriteFilmIds" : [1,2,3] },
{ "_id" : 3, "name" : "Vasil" }
)
И коллекция фильмов со следующими документами:
filmModel.create(
{ "_id" : 1, "name": "Titanic", genre: "drama" },
{ "_id" : 2, "name": "Lord of the Rings", genre: "fantasy" },
{ "_id" : 3, "name": "The King's Speech", genre: "drama" },
{ "_id" : 4, "name": "Gentleman", genre: "Action" },
{ "_id" : 5, "name": null },
)
Для того, чтобы вытянуть пользователей вместе с их любимыми фильмами, воспользуемся aggregate:
userModel.aggregate([
{
$lookup:
{
// название колекции фильмов
from: "films", // название колекции, а не модели!!!!
// поле в колекции пользователей, которое содержит id любимых фильмов
localField: "favouriteFilmIds",
// поле в колекции фильмов, которое должно отвечать id фильмов в
// коллекции пользователей
foreignField: "_id",
// как поле с документами фильмов будет называтся
as: "favouriteFilms"
}
}
])
В результате получим что-то вроде:
[
{
"_id" : 1,
"name" : "Ivan",
"favouriteFilmIds" : [1,3,5],
"favouriteFilms": [
{ "_id" : 1, "name": "Titanic", genre: "drama" },
{ "_id" : 3, "name": "The King's Speech", genre: "drama" },
{ "_id" : 5, "name": null }
]
},
{
"_id" : 2,
"name" : "Igor",
"favouriteFilmIds" : [1,2,3],
"favouriteFilms": [
{ "_id" : 1, "name": "Titanic", genre: "drama" },
{ "_id" : 2, "name": "Lord of the Rings", genre: "fantasy" },
{ "_id" : 3, "name": "The King's Speech", genre: "drama" },
]
},
{
"_id" : 3,
"name" : "Vasil",
"favouriteFilms": []
}
]
Помимо оператора $ lookup для вытягивания взаимосвязанных данных из разных коллекций, в aggregate есть еще много других операторов.
Для выполнения этих действий одно за другим мы можем прописать их в различных объектах аргумента-массива aggregate. Это называется aggregation pipeline. Например, нам нужно исключить из результата поиска выше favouriteFilmIds, так как достаточно наличия favouriteFilms. Для этого модифицируем наш предыдущий запрос оператором unset:
userModel.aggregate([
{
$lookup:
{
from: "films",
localField: "favouriteFilmIds",
foreignField: "_id",
as: "favouriteFilms"
}
},
{
$unset: ["favouriteFilmIds"]
}
])
Last updated
Was this helpful?