Mongoose聚合操作后如何关联填充employeeId字段?
在MongoDB Aggregate中关联填充员工信息
问题描述
我需要将考勤文档中的employeeId字段关联填充对应的name、employeeCode、department和fulltime信息。之前用myCollection.find()时populate功能正常,但现在必须使用myCollection.aggregate,而这个方法不能直接用populate。以下是我的文档结构和当前的GET接口代码,请问该如何实现关联填充?
考勤文档结构
_id: ObjectId('64036f7ac0829fe25c6ef435') clockIn: 2023-03-04T06:28:06.433+00:00 clockOut: 2023-03-04T10:30:08.601+00:00 employeeId: ObjectId('63feed3c60a04fbc61c52f91') createdAt: 2023-03-04T16:19:06.436+00:00 updatedAt: 2023-03-04T16:19:08.601+00:00 __v: 0
当前GET接口代码
timesheetRouter.get('/timesheet', async (req, res) => { try { const clockInOutTimesheet = await Timesheet.aggregate([ { $group: {_id: '$employeeId', totalHours: { $sum: { $subtract: ['$clockOut', '$clockIn'] } }, }, }, ]) console.log("GET ==> ",clockInOutTimesheet) res.json(clockInOutTimesheet); } catch (err) { console.error(err); res.status(500).json({ message: 'Server Error' }); } });
解决方案
在MongoDB聚合管道中,使用$lookup阶段可以实现类似populate的关联查询,将员工集合的信息关联到考勤分组结果中。具体实现步骤如下:
修改后的完整代码
timesheetRouter.get('/timesheet', async (req, res) => { try { const clockInOutTimesheet = await Timesheet.aggregate([ // 按employeeId分组,计算该员工的总工时 { $group: { _id: '$employeeId', totalHours: { // 计算毫秒数,如需转小时可套$divide: [结果, 3600000] $sum: { $subtract: ['$clockOut', '$clockIn'] } } } }, // 关联员工集合,匹配_id与employeeId { $lookup: { from: 'employees', // 替换为你的员工集合实际名称 localField: '_id', foreignField: '_id', as: 'employee' // 关联结果存入employee数组 } }, // 展开employee数组,同时保留无匹配的分组数据 { $unwind: { path: '$employee', preserveNullAndEmptyArrays: true } }, // 构造输出结构,提取需要的字段 { $project: { _id: 0, // 可选,隐藏原分组的_id employeeId: '$_id', totalHours: 1, name: '$employee.name', employeeCode: '$employee.employeeCode', department: '$employee.department', fulltime: '$employee.fulltime' } } ]) console.log("GET ==> ", clockInOutTimesheet) res.json(clockInOutTimesheet); } catch (err) { console.error(err); res.status(500).json({ message: 'Server Error' }); } });
关键说明
- 替换
$lookup中的from值为你的员工集合实际名称。 - 如果需要将总工时从毫秒转为小时,修改
totalHours的计算逻辑:totalHours: { $divide: [ { $sum: { $subtract: ['$clockOut', '$clockIn'] } }, 3600000 // 1小时 = 3600000毫秒 ] } preserveNullAndEmptyArrays: true确保即使分组没有匹配到员工数据,也会保留该分组的工时信息,避免数据丢失。
内容的提问来源于stack exchange,提问作者Weslley Fortunato
相关产品推荐
相关产品推荐

