Как применить условие к результату $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
}
Другие вопросы по тегам