如何在外键上进行条件聚合查找

时间:2019-05-01 18:52:11

标签: node.js mongodb aggregation-framework

经过多次尝试,我无法很好地对集合进行有条件的汇总。

我使用两个集合:

种族,其中包含评论

我只需要为第二条管道获得发布的评论。 我不想使用$project。 是否可以仅使用$match? 当我使用localField,foreignField时,它可以完美工作,但是我只需要过滤已发布的评论。 我为此付出了很多努力,我不明白为什么let没有给我ForeignKey。 我尝试过:_id$reviews等。

我的$lookup如下:

{
    $lookup: {
      from: "reviews",
      as: "reviews",
      let: { reviewsId: "$_id" },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                // If I comment the next line, it give all the reviews to all the races
                { $eq: ["$_id", "$$reviewsId"] },
                { $eq: ["$is_published", true] }
              ]
            }
          }
        }
      ]

      // localField: "reviews",
      // foreignField: "_id"
    }
  },

种族的示例:

{  
   "description":"Nice race",
   "attendees":[  

   ],
   "reviews":[  
      {  
         "$oid":"5c363ddcfdab6f1d822d7761"
      },
      {  
         "$oid":"5cbc835926fa61bd4349a02a"
      }
   ],
   ...
}

评论的示例:

{  
   "_id":"5c3630ac5d00d1dc26273dab",
   "user_id":"5be89576a38d2b260bfc1bfe",
   "user_pseudo":"gracias",
   "is_published":true,
   "likes":[],
   "title":"Best race",
   "__v":10,
   ...
}

我很快就会发疯:'(... 如何做到这一点?

2 个答案:

答案 0 :(得分:1)

您的问题是这一行:

        { $eq: ["$is_published", true] }

您正在使用此文档_id字段来匹配评论。

正确的版本如下:

(

    [
        { 
            "$unwind" : "$reviews"
        }, 
        { 
            "$lookup" : {
                "from" : "reviews", 
                "as" : "reviews", 
                "let" : {
                    "reviewsId" : "$reviews"
                }, 
                "pipeline" : [
                    {
                        "$match" : {
                            "$expr" : {
                                "$and" : [
                                    {
                                        "$eq" : [
                                            "$_id", 
                                            "$$reviewsId"
                                        ]
                                    },
                                     { $eq: ["$is_published", true] }
                                ]
                            }
                        }
                    }
                ]
            }
        }
    ], 
);

现在,如果要恢复旧结构,请添加:

{
  $group: {
           _id: "$_id",
           reviews: {$push: "$reviews"},
   }
}

答案 1 :(得分:1)

首先,您必须输入正确的字段以从引用的集合(即reviews)中获取数据。其次,您需要使用$in聚合运算符,因为您的reviews字段是ObjectId的数组。

db.getCollection('races').aggregate([
  { "$lookup": {
    "from": "reviews",
    "let": { "reviews": "$reviews" },
    "pipeline": [
      { "$match": {
        "$expr": { "$in": [ "$_id", "$$reviews" ] },
        "is_published": true
      }}
    ],
    "as": "reviews"
  }}
])