MongoDB聚合查询如何筛选带未来会议的已验证学生并排序
MongoDB聚合查询获取带未来会议的已验证学生解决方案
你现有代码的核心问题是:$match: {'meetup.startTime': {$gte: xxx}}仅能筛选出「至少包含一场符合时间要求会议的学生」,不会对meetup数组内部的元素做过滤,因此会返回学生名下的所有历史会议。
优化后的查询逻辑
- 关联会议表前先过滤已验证学生,减少后续关联的数据量
- 使用
$filter操作符过滤meetup数组,仅保留未来时间的会议 - 过滤掉无未来会议的学生(即
meetup数组为空的记录) - 新增
latestMeetupTime字段存储学生最近的会议时间,用于排序
完整代码
// 定义未来会议的时间阈值,可按需修改,示例为当前时间 const FUTURE_MEETUP_THRESHOLD = new Date(); // 也可使用你示例中的固定时间:new Date('2021-09-10T08:41:15.746Z') const aggregateDataQuery = [ // 1. 先过滤已验证学生 { $match: { verified: true } }, // 2. 关联会议表 { $lookup: { from: 'meetup', localField: '_id', foreignField: 'studentId', as: 'meetup', }, }, // 3. 过滤meetup数组仅保留未来会议,同时计算最近会议时间用于排序 { $addFields: { meetup: { $filter: { input: "$meetup", as: "m", cond: { $gte: ["$$m.startTime", FUTURE_MEETUP_THRESHOLD] } } }, latestMeetupTime: { $min: "$meetup.startTime" } } }, // 4. 过滤掉没有未来会议的学生 { $match: { meetup: { $ne: [] } } }, // 5. 保留需要返回的字段 { $project: { firstName: 1, lastName: 1, email: 1, meetup: { _id: 1, startTime: 1, }, latestMeetupTime: 1 }, }, ]; const [result, err] = await of( Student.aggregate([ ...aggregateDataQuery, { $facet: { data: [ // 按最近会议时间升序排序,越近的排在越前面 { $sort: { latestMeetupTime: 1 } }, { $skip: skip }, { $limit: recordLimit }, // 不需要返回latestMeetupTime可打开下方注释移除该字段 // { $project: { latestMeetupTime: 0 } } ], count: [ { $count: 'count', }, ], }, }, ]) );
补充说明
- 排序规则可按需调整,将
{ latestMeetupTime: 1 }改为{ latestMeetupTime: -1 }即可实现会议时间越近排名越靠后。
内容的提问来源于stack exchange,提问作者Mani
相关产品推荐
相关产品推荐

