如何在MongoDB Aggregate Lookup中添加条件实现指定查询
问题需求
我有两个MongoDB集合:university和college,一个大学对应多个学院。需要按以下条件获取大学与学院的详情:
- 先筛选出下属学院数量最多的大学;
- 再获取该大学中学生人数最多的学院。
注意:即使某大学学院数量少但总学生数更多,也必须优先满足条件1,再满足条件2
已尝试内容
University集合单条数据示例
{ _id: new ObjectId("62f5557f6c96453a1e972fe8"), UniversityId: 1, Name: 'Tigor University', State: 'Delhi', PhoneNumber: 9856897895 }
College集合单条数据示例
{ "_id": "62f563d16aeb1d12cddca85a", "ClgId": 3, "UniversityId": 5, "Name": "Renuka College Of Science", "Email": "avinandanmd@renukaclg.com", "PhoneNumber": 9999663302, "TotalStudent": 8900 }
现有API代码
router.get('/universityDetail', async (req,res)=>{ let universityDetail = await universityModel.aggregate([ { $lookup: { from:'colleges', localField:'UniversityId', foreignField:'UniversityId', as:'collegedetail' } } ]); res.send(universityDetail); })
当前接口响应
[ { "_id": "62f5557f6c96453a1e972fe8", "UniversityId": 1, "Name": "Tigor University", "State": "Delhi", "PhoneNumber": 9856897895, "collegedetail": [] }, { "_id": "62f5557f6c96453a1e972fe8", "UniversityId": 2, "Name": "Royal University", "State": "Pune", "PhoneNumber": 8585858585, "collegedetail": [] }, { "_id": "62f5557f6c96453a1e972fe8", "UniversityId": 3, "Name": "Golaknath CH University", "State": "Bihar", "PhoneNumber": 3356898548, "collegedetail": [ { "_id": "62f563d16aeb1d12cddca85a", "ClgId": 3, "UniversityId": 3, "Name": "Renuka College Of Science", "Email": "avinandanmd@renukaclg.com", "PhoneNumber": 9999663302, "TotalStudent": 8900 } ] }, { "_id": "62f5557f6c96453a1e972fe8", "UniversityId": 4, "Name": "Sankalp B University", "State": "MP", "PhoneNumber": 9856897895, "collegedetail": [ { "_id": "62f563d16aeb1d12cddca85a", "ClgId": 6, "UniversityId": 4, "Name": "Jyoti Vidya Ayurveda College", "Email": "jvacCamp@jvmc.com", "PhoneNumber": 2359568, "TotalStudent": 800 }, { "_id": "62f563d16aeb1d12cddca85a", "ClgId": 9, "UniversityId": 4, "Name": "Sino Reddy College", "Email": "sinoredycollege@yahoo.com", "PhoneNumber": 9999663302, "TotalStudent": 1200 } ] }, { "_id": "62f5557f6c96453a1e972fe8", "UniversityId": 5, "Name": "Periya", "State": "Delhi", "PhoneNumber": 9856897895, "collegedetail": [] } ]
期望结果
{ "_id": "62f5557f6c96453a1e972fe8", "UniversityId": 4, "Name": "Sankalp B University", "State": "MP", "PhoneNumber": 9856897895, "collegedetail": [ { "_id": "62f563d16aeb1d12cddca85a", "ClgId": 9, "UniversityId": 4, "Name": "Sino Reddy College", "Email": "sinoredycollege@yahoo.com", "PhoneNumber": 9999663302, "TotalStudent": 1200 } ] }
解决方案
修改聚合管道,通过多阶段操作满足需求:
router.get('/universityDetail', async (req,res)=>{ let universityDetail = await universityModel.aggregate([ // 关联学院数据 { $lookup: { from:'colleges', localField:'UniversityId', foreignField:'UniversityId', as:'collegedetail' }}, // 计算每个大学的学院数量 { $addFields: { collegeCount: { $size: "$collegedetail" } }}, // 按学院数量降序排序,学院数最多的排第一 { $sort: { collegeCount: -1 }}, // 只保留第一个(学院数最多的大学) { $limit: 1 }, // 对该大学的学院按学生数降序排序 { $addFields: { collegedetail: { $sortArray: { input: "$collegedetail", sortBy: { TotalStudent: -1 } } } }}, // 只保留学生数最多的那个学院 { $addFields: { collegedetail: { $slice: ["$collegedetail", 1] } }} ]); // 返回结果(因为limit后是数组,取第一个元素) res.send(universityDetail[0]); })
步骤解释
- $lookup:关联
colleges集合,获取每个大学对应的所有学院; - $addFields:新增
collegeCount字段,计算当前大学的学院数量; - $sort:按
collegeCount降序排序,确保学院数量最多的大学排在首位; - $limit:只保留排序后的第一条数据,即学院数量最多的大学;
- $sortArray:对该大学的学院列表按
TotalStudent降序排序,学生数最多的学院排第一; - $slice:截取学院列表的第一个元素,只保留学生数最多的学院;
- 最后返回结果数组的第一个元素,符合期望的单条数据格式。
内容的提问来源于stack exchange,提问作者Sensei_75
相关产品推荐
相关产品推荐

