如何使用数组嵌入对象值来投影eq聚合

时间:2019-08-25 08:13:20

标签: mongodb mongodb-query

我有一个like数组,其中包含一个喜欢文档中嵌入的图像的用户列表。当用户喜欢传递了user_id参数的照片时,我想返回布尔值。

我使用$ eq聚合,但是它只接受类似数组的最新对象。如果一个数组只有一个对象,它将返回正确的值;如果一个数组有多个对象,它将仅查找最新的对象。我必须这样做,以便它可以找到数组中的所有对象并返回正确的值。

"likes" : [ 
        {
            "user_id" : ObjectId("")
        }, 
        {
            "user_id" : ObjectId("")
        }
  ],

db.getCollection('photos').aggregate(
    [
        {
            $match: {
            status: '1'
            }
        },

        {
            $project: {
                like_count:{$size:"$likes"},
                is_liked: {$eq: ["$likes.user_id", [ObjectId("")]]},
                _id:1,
                title:1
            }
        },
    ]
);

2 个答案:

答案 0 :(得分:1)

以下查询可以为我们提供预期的输出:

db.photos.aggregate([
    {
        $match:{
            "status":"1"
        }
    },
    {
        $project:{
            "_id":1,
            "title":1,
            "like_count":{
                $size:"$likes"
            },
            "is_liked":{
                $in:[{ "user_id" : ObjectId("5d626ad2f00e0c8c3593b60e") }, "$likes"]
            }
        }
    }
]).pretty()

数据集:

{
    "_id" : ObjectId("5d626b0bf00e0c8c3593b610"),
    "title" : "Cool",
    "status" : "1",
    "likes" : [
        {
            "user_id" : ObjectId("5d626ad2f00e0c8c3593b60e")
        },
        {
            "user_id" : ObjectId("5d626addf00e0c8c3593b60f")
        }
    ]
}

输出:

{
    "_id" : ObjectId("5d626b0bf00e0c8c3593b610"),
    "title" : "Cool",
    "like_count" : 2,
    "is_liked" : true
}

我们正在根据用户ID准备文档,以使用$in运算符搜索并检查该文档是否存在于likes数组中。

答案 1 :(得分:0)

用它替换is_liked逻辑,在您的查询中mongo只匹配数组的第一个元素,因此您需要过滤数组以检查user_id的出现,以及如果过滤器返回非空数组(如true,否则为false)

{
    $project: {
      is_liked: {
        $cond: {
          if: {
            $gt: [
              {
                $size: {
                  $filter: {
                    input: "$likes",
                    as: "item",
                    cond: {
                      $eq: [
                        "$$item.user_id",
                        ObjectId("")                          ]
                    }
                  }
                }
              },
              0
            ]
          },
          then: true,
          else: false
        }
      }
    }
  }