如何在mongodb中通过查找有限制的项目来匹配并跳过

问题描述 投票:0回答:1

我有 2 个集合,分别是 users 和 user_courses。 user_courses集合是一个多对多的连接表。我需要通过分页注册课程来过滤用户。

用户集合看起来像:

[
    {
        "_id": ObjectId("123"),
        "name": "Lorem Ipsum",
        "email": "[email protected]"
    },
    {
        "_id": ObjectId("234"),
        "name": "Lorem Ipsum",
        "email": "[email protected]"
    },
    {
        "_id": ObjectId("345"),
        "name": "Lorem Ipsum",
        "email": "[email protected]"
    },
    ...
]

和 user_course 集合看起来像:

[
    {
        "_id": ObjectId("12345"),
        "userId": ObjectId("123"),
        "courseId": ObjectId("111"),
    },
    {
        "_id": ObjectId("23456"),
        "userId": ObjectId("123"),
        "courseId": ObjectId("222"),
    },
    {
        "_id": ObjectId("34567"),
        "userId": ObjectId("123"),
        "courseId": ObjectId("333"),
    },
    {
        "_id": ObjectId("45678"),
        "userId": ObjectId("234"),
        "courseId": ObjectId("222"),
    },
    {
        "_id": ObjectId("56789"),
        "userId": ObjectId("345"),
        "courseId": ObjectId("111"),
    },
    {
        "_id": ObjectId("67890"),
        "userId": ObjectId("345"),
        "courseId": ObjectId("222"),
    },
    ...
]

这是我的代码:

const filterObj = {
    "$or": [
        {
            "name": {
                $regex: searchKey
            }
        },
        {
            "email": {
                $regex: searchKey
            }
        }
    ]
}

Users.aggregate([
    { $match: filterObj },
    { $sort: { createdAt: -1 } },
    { $skip: skip },
    { $limit: limit },
    {
        $lookup: {
            from: 'user_courses',
            localField: '_id',
            foreignField: 'userId',
            as: 'userCourses',
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                {
                                    $eq: [
                                        "$courseId",
                                        new mongoose.Types.ObjectId(courseId)
                                    ]
                                }
                            ]
                        }
                    }
                }
            ]
        }
    },
    {
        $unwind: "$userCourses"
    }
])

使用此代码,它会获取前 10 个项目(限制:10 并跳过:0),然后使用管道中的匹配过滤结果。如果我删除展开选项,它只会在查找值内应用过滤器并返回所有用户,即使 userCourses 查找为空。

如何在排序、跳过和限制之前按注册课程过滤用户?

mongodb mongoose aggregation-framework
1个回答
0
投票

一个选项是:

db.users.aggregate([
  { $match: filterObj },
  {
    $sort: {
      createdAt: -1
    }
  },
  {
    $lookup: {
      from: "user_courses",
      as: "userCourses",
      localField: "_id",
      foreignField: "userId",
      pipeline: [
        {
          $match: {
            "courseId": new mongoose.Types.ObjectId(courseId)
          }
        }
      ]
    }
  },
  {
    $match: {
      "userCourses.0": {
        $exists: true
      }
    }
  },
  {
    $unset: "userCourses"
  },
  {
    $skip: skip
  },
  {
    $limit: limit
  }
])
© www.soinside.com 2019 - 2024. All rights reserved.