Как применить условие к результату $lookup в mongoDB?
Со ссылкой на мой предыдущий вопрос у меня возник вопрос о $lookup с добавлением некоторых условий. Вы можете получить достаточно ссылки на вопрос из описания ссылки ниже.
Фото:
{_id: 1, photo_name: '1.jpg', photo_description: 'description 1', album_id: 1, flag:1 },
{_id: 2, photo_name: '2.jpg', photo_description: 'description 2', album_id: 1, flag:1 },
{_id: 3, photo_name: '3.jpg', photo_description: 'description 3', album_id: 1, flag:1 },
{_id: 4, photo_name: '4.jpg', photo_description: 'description 4', album_id: 2, flag:0 },
{_id: 5, photo_name: '5.jpg', photo_description: 'description 5', album_id: 2, flag:0 },
{_id: 6, photo_name: '6.jpg', photo_description: 'description 6', album_id: 2}
Альбом:
{_id: 1, album_name: "my album 1", album_description: "album description 1", emoji_id: 1},
{_id: 2, album_name: "my album 2", album_description: "album description 2", emoji_id: 2},
{_id: 3, album_name: "my album 3", album_description: "album description 3", emoji_id: 3},
{_id: 4, album_name: "my album 4", album_description: "album description 4", emoji_id: 4},
{_id: 5, album_name: "my album 5", album_description: "album description 5", emoji_id: 5}
Emoji:
{_id: 1, emoji_name: "1.jpg"},
{_id: 2, emoji_name: "2.jpg"},
{_id: 3, emoji_name: "3.jpg"},
{_id: 4, emoji_name: "4.jpg"},
{_id: 5, emoji_name: "5.jpg"},
{_id: 6, emoji_name: "6.jpg"},
{_id: 7, emoji_name: "7.jpg"},
{_id: 8, emoji_name: "8.jpg"}
Тестовая запись пагинации:
2
Предположим, я добавил одно другое поле флага в коллекцию фотографий, и теперь я хочу, чтобы считались только те фотографии, флаг которых равен единице.
Я попытался добавить $ match сразу после $lookup в запросе, но это не удалось. Он не исключает фотографии, флаг которых =0, а также в счетчике не помечает условие.
Текущий результат Есть 3 фотографии из 10 фотографий с установленным флагом 0. И мы не можем рассматривать те фотографии, чей флаг равен 0. Таким образом, ожидаемое общее количество составляет 7 фотографий, но количество возвращает 10 фотографий, хотя я применил условие флага на фотографиях.
Настоящий запрос:
db
.album
.aggregate([
{
$lookup:{
from:"photo",
localField:"_id",
foreignField:"album_id",
as:"photo"
}
},
{
$match:{
"photo.flag": 1
}
},
{
$lookup:{
from:"emoji",
localField:"album_emoji",
foreignField:"_id",
as:"emoji"
}
},
{
$project:{
album_name:"$album_name",
album_description:"$album_description",
album_emoji:"$emoji.image_name",
photo:"$photo",
total_photos: {$size: "$photo"}
}
}
])
.toArray();
Ожидаемый результат:
[
{
"_id" : 1,
"album_name" : "Album 1",
"album_description" : "Album description 1",
"album_emoji" : [
"1.jpg"
],
"total_photos" : 3,
"photo" : [
{
"_id" : 1,
"album_id" : 1,
"photo_description" : "description 1",
"photo_name" : "1.jpg",
"flag" : 0,
},
{
"_id" : 2,
"album_id" : 1,
"photo_description" : "description 2",
"photo_name" : "2.jpg",
"flag" : 0,
},
{
"_id" : 1,
"album_id" : 1,
"photo_description" : "description 3",
"photo_name" : "3.jpg",
"flag" : 0,
}
]
}
]
Текущий вывод:
[
{
"_id" : 1,
"album_name" : "Album 1",
"album_description" : "Album description 1",
"album_emoji" : [
"1.jpg"
],
"total_photos" : 5,
"photo" : [
{
"_id" : 1,
"album_id" : 1,
"photo_description" : "description 1",
"photo_name" : "1.jpg",
"flag" : 1,
},
{
"_id" : 2,
"album_id" : 1,
"photo_description" : "description 2",
"photo_name" : "2.jpg",
"flag" : 1,
},
{
"_id" : 3,
"album_id" : 1,
"photo_description" : "description 3",
"photo_name" : "3.jpg",
"flag" : 1,
},
{
"_id" : 4,
"album_id" : 1,
"photo_description" : "description 4",
"photo_name" : "4.jpg",
"flag" : 0,
},
{
"_id" : 5,
"album_id" : 1,
"photo_description" : "description 5",
"photo_name" : "5.jpg",
"flag" : 0,
}
]
}
]
2 ответа
Вы не можете использовать "$match" с методом объекта после "$lookup", потому что возвращаемое значение "$ lookup" является значениями массива. Вам лучше добавить функцию "$unwind" после поиска, а затем сгруппировать ее.
Пример запроса
db
.album
.aggregate([
{
$lookup:{
from:"photo",
localField:"_id",
foreignField:"album_id",
as:"photo"
}
},
{
preserveNullAndEmptyArrays : true,
path : "$photo"
},
{
$match:{
"photo.flag": 1
}
},
{
$group : {
_id : {
id : "$_id",
album_name: "$album_name",
album_description: "$album_description",
emoji_id: "$emoji_id"
},
photo: {
$push : "$photo"
}
}
}
{
$lookup:{
from:"emoji",
localField:"_id.album_emoji",
foreignField:"_id",
as:"emoji"
}
},
{
$project:{
album_name:"$album_name",
album_description:"$album_description",
emoji:"$emoji",
photo:"$photo",
total_photos: {$size: "$photo"}
}
}
])
Или используйте "фильтр $".
db
.album
.aggregate([
{
$lookup:{
from:"photo",
localField:"_id",
foreignField:"album_id",
as:"photo"
}
},
{
$project: {
id : "$_id",
album_name: "$album_name",
album_description: "$album_description",
emoji_id: "$emoji_id",
photo: {
$filter : {
input: "$photo",
as : "photo_field",
cond : {
$eq: ["$$photo_field.flag",1]
}
}
}
}
},
{
$lookup:{
from:"emoji",
localField:"album_emoji",
foreignField:"_id",
as:"emoji"
}
},
{
$project:{
album_name:"$album_name",
album_description:"$album_description",
emoji:"$emoji",
photo:"$photo",
total_photos: {$size: "$photo"}
}
}
])
Ваш запрос неверен. Что такое localField:"album_emoji"
нет поля с именем album_emoji
в Album
коллекция. Имя поля album_id
в Album
Коллекция, которая является внешним ключом к _id
в Emoji
коллекция.
Если вы используете версию 3.5, правильный запрос (я предполагаю, Album
, Photo
, Emoji
имена трех коллекций):
db.Album.aggregate([
{
$lookup:{
from:"Photo",
localField:"_id",
foreignField:"album_id",
as:"photo"
}
},
{
$match:{
"photo.flag": 1
}
},
{
$lookup:{
from:"Emoji",
localField:"emoji_id",
foreignField:"_id",
as:"emoji"
}
},
{
$project:{
album_name:"$album_name",
album_description:"$album_description",
album_emoji:"$emoji.emoji_name",
photo:"$photo",
total_photos: {$size: "$photo"}
}
}
]).pretty()
И результат таков:
/* 1 */
{
"_id" : 1,
"album_name" : "my album 1",
"album_description" : "album description 1",
"album_emoji" : [
"1.jpg"
],
"photo" : [
{
"_id" : 1,
"photo_name" : "1.jpg",
"photo_description" : "description 1",
"album_id" : 1,
"flag" : 1
},
{
"_id" : 2,
"photo_name" : "2.jpg",
"photo_description" : "description 2",
"album_id" : 1,
"flag" : 1
},
{
"_id" : 3,
"photo_name" : "3.jpg",
"photo_description" : "description 3",
"album_id" : 1,
"flag" : 1
}
],
"total_photos" : 3
}