我有 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 查找为空。
如何在排序、跳过和限制之前按注册课程过滤用户?
一个选项是:
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
}
])