在 MongoDb 中使用查找和限制条件聚合查询

Agregate query with lookup and restriction condition in MongoDb

我有一个 collection 我的收藏

{
   name : String,
   members: [{status : Number, memberId : {type: Schema.Types.ObjectId, ref: 'members'}]
}

使用此数据:

"_id" : ObjectId("5e8b0bac041a913bc608d69d")
  "members" : [ 
        {
            "status" : 4,
            "_id" : ObjectId("5e8b0bac041a913bc608d69e"),
            "memberId" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
            "date" : ISODate("2020-04-06T10:59:56.997Z")
        }, 
        {
            "status" : 1,
            "_id" : ObjectId("5e8b0bf2041a913bc608d6a3"),
            "memberId" : ObjectId("5e7e2f048f80b46d786bfd67"),
            "date" : ISODate("2020-04-06T11:01:06.463Z")
        }
    ],

和 collection 成员

{
  firstname : String
  lastname  : String
} 

使用此数据:

  [{
        "_id" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
        "firstname" : "raed",
        "lastname" : "besbes"
    }, 
    {
        "_id" : ObjectId("5e7e2f048f80b46d786bfd67"),
        "firstname" : "sarra",
        "lastname" : "besbes"
    }]

我使用聚合和 $lookup 进行查询,以填充数据,但我想限制返回 仅状态 1 的数据,这是我的查询和结果。 如何获取仅返回状态为 1 的成员的数据?谢谢。

查询

db.getCollection('myCollection').aggregate([
        { $match: { _id: ObjectId("5e8b0bac041a913bc608d69d")}},
       {
            "$lookup": {
                "from": "members",
                "localField": "members.memberId",
                "foreignField": "_id",
                "as": "Members"
            }
        },
        {
            $project: {
                "Members.firstname" : 1,
                "Members.lastname" : 1,
                "Members._id" : 1,
                },

        }


    ])

结果

{
    "_id" : ObjectId("5e8b0bac041a913bc608d69d"),
    "Members" : [ 
        {
            "_id" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
            "firstname" : "raed",
            "lastname" : "besbes"
        }, 
        {
            "_id" : ObjectId("5e7e2f048f80b46d786bfd67"),
            "firstname" : "sarra",
            "lastname" : "besbes"
        }
    ]
}

选项 1

$lookup

之前过滤 members
db.myCollection.aggregate([
  {
    $match: {
      _id: ObjectId("5e8b0bac041a913bc608d69d")
    }
  },
  {
    $addFields: {
      members: {
        $filter: {
          input: "$members",
          cond: {
            $eq: [
              "$$this.status",
              1
            ]
          }
        }
      }
    }
  },
  {
    "$lookup": {
      "from": "members",
      "localField": "members.memberId",
      "foreignField": "_id",
      "as": "Members"
    }
  },
  {
    $project: {
      "Members.firstname": 1,
      "Members.lastname": 1,
      "Members._id": 1
    }
  }
])

MongoPlayground

选项 2

(类似于1)我们展平member数组,只过滤status = 1然后执行$lookup.

db.myCollection.aggregate([
  {
    $match: {
      _id: ObjectId("5e8b0bac041a913bc608d69d")
    }
  },
  {
    "$unwind": "$members"
  },
  {
    $match: {
      "members.status": 1
    }
  },
  {
    "$lookup": {
      "from": "members",
      "localField": "members.memberId",
      "foreignField": "_id",
      "as": "Members"
    }
  },
  {
    "$unwind": "$Members"
  },
  {
    $group: {
      _id: "$_id",
      Members: {
        $push: "$Members"
      }
    }
  }
])

MongoPlayground

选项 3

我们可以根据 member 数组的过滤值对 Member 数组应用过滤器。

db.myCollection.aggregate([
  {
    $match: {
      _id: ObjectId("5e8b0bac041a913bc608d69d")
    }
  },
  {
    "$lookup": {
      "from": "members",
      "localField": "members.memberId",
      "foreignField": "_id",
      "as": "Members"
    }
  },
  {
    $project: {
      Members: {
        $filter: {
          input: "$Members",
          cond: {
            $in: [
              "$$this._id",
              {
                $let: {
                  vars: {
                    input: {
                      $filter: {
                        input: "$members",
                        cond: {
                          $eq: [
                            "$$this.status",
                            1
                          ]
                        }
                      }
                    }
                  },
                  in: "$$input.memberId"
                }
              }
            ]
          }
        }
      }
    }
  }
])

MongoPlayground