You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过MongoDB聚合查询员工月度缺勤日期并生成考勤表

月度考勤统计聚合查询方案

针对你提到的场景(员工打卡生成考勤文档,未打卡无记录),可以通过MongoDB聚合管道生成指定员工的月度考勤表,完整统计打卡日期与缺勤日期。

核心思路

  1. 筛选指定员工、指定月份的所有考勤记录;
  2. 生成目标月份的完整日期列表;
  3. 将考勤记录与日期列表做左关联,匹配到的为打卡日期,未匹配的即为缺勤日期;
  4. 统一整理结果,标记每个日期的考勤状态。

聚合查询代码(Mongoose 实现)

假设目标员工ID为employeeId,统计月份为targetMonth(格式如2022-12):

const ObjectId = require('mongoose').Types.ObjectId;
const targetMonth = "2022-12"; // 示例统计月份
const employeeId = new ObjectId("638869649c443988469c151f"); // 示例员工ID

// 解析月份的起始/结束UTC时间
const [year, month] = targetMonth.split('-').map(Number);
const startOfMonth = new Date(Date.UTC(year, month - 1, 1));
const endOfMonth = new Date(Date.UTC(year, month, 1));

Attendance.aggregate([
  // 阶段1:筛选指定员工+月份的考勤记录
  {
    $match: {
      user: employeeId,
      date: { $gte: startOfMonth, $lt: endOfMonth }
    }
  },
  // 阶段2:提取日期(仅保留年月日)与关键考勤字段
  {
    $project: {
      attendanceDate: {
        $dateToString: { format: "%Y-%m-%d", date: "$date", timezone: "Asia/Karachi" } // 需匹配数据库date字段的时区,示例为巴基斯坦时区
      },
      status: 1,
      check_in: 1,
      check_out: 1,
      totalHours: 1
    }
  },
  // 阶段3:分面处理:保留考勤记录+生成当月完整日期列表
  {
    $facet: {
      attendanceRecords: [{ $match: {} }],
      allMonthDates: [
        {
          $group: {
            _id: null,
            existingDates: { $push: "$attendanceDate" }
          }
        },
        {
          $project: {
            _id: 0,
            absentDates: {
              $setDifference: [
                {
                  $map: {
                    input: { $range: [0, { $dayOfMonth: endOfMonth }] },
                    as: "day",
                    in: {
                      $dateToString: {
                        format: "%Y-%m-%d",
                        date: { $add: [startOfMonth, { $multiply: ["$$day", 86400000] }] },
                        timezone: "Asia/Karachi"
                      }
                    }
                  }
                },
                "$existingDates"
              ]
            }
          }
        }
      ]
    }
  },
  // 阶段4:合并打卡/缺勤记录,生成统一结构的考勤列表
  {
    $project: {
      attendanceList: {
        $concatArrays: [
          // 处理打卡记录
          {
            $map: {
              input: "$attendanceRecords",
              as: "record",
              in: {
                date: "$$record.attendanceDate",
                status: "$$record.status",
                check_in: "$$record.check_in",
                check_out: "$$record.check_out",
                totalHours: "$$record.totalHours",
                type: "打卡"
              }
            }
          },
          // 处理缺勤记录
          {
            $map: {
              input: { $arrayElemAt: ["$allMonthDates.absentDates", 0] },
              as: "date",
              in: {
                date: "$$date",
                status: "absent",
                type: "缺勤"
              }
            }
          }
        ]
      }
    }
  },
  // 阶段5:按日期排序并整理最终结果
  { $unwind: "$attendanceList" },
  { $sort: { "attendanceList.date": 1 } },
  {
    $group: {
      _id: null,
      monthlyAttendance: { $push: "$attendanceList" }
    }
  },
  { $project: { _id: 0, monthlyAttendance: 1 } }
]).then(result => {
  console.log('月度考勤表:', result[0]?.monthlyAttendance || []);
}).catch(err => {
  console.error('查询失败:', err);
});

关键说明

  • 时区匹配:$dateToString中的timezone必须和数据库date字段的时区一致,否则会出现日期匹配错误;
  • 缺勤日期计算:通过$range生成当月所有日期,再用$setDifference排除已有打卡记录的日期,得到缺勤日期;
  • 扩展优化:若需排除周末/节假日,可在生成日期列表阶段添加$filter逻辑,筛选出工作日。

内容的提问来源于stack exchange,提问作者hamza irfan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:05:30