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

使用Mongoose分组时如何对字段求和并获取预期统计结果?

解决Mongoose分组求和的完整统计问题

看起来你现在的聚合查询只返回了部分日期的统计结果,问题大概率出在两个地方:要么是$match阶段不小心过滤掉了3月31日的那条数据,要么是分组逻辑没有覆盖到你想要的统计维度。我分几种常见的需求场景给你对应的解决方案:

场景1:按日期(年/月/日)统计每日总记录数

如果你想得到所有日期的总记录数(包括只有1条数据的3月31日),可以用下面的聚合管道:

// 替换成你的Model名称
YourModel.aggregate([
  // 如果不需要过滤条件,直接删除$match阶段;如果需要过滤,确保条件包含所有要统计的记录
  // { $match: { /* 你的过滤条件,比如status的范围等 */ } },
  {
    $group: {
      _id: {
        year: { $year: "$createdAt" },
        month: { $month: "$createdAt" },
        day: { $dayOfMonth: "$createdAt" }
      },
      count: { $sum: 1 }
    }
  },
  // 可选:按日期升序排序,让结果更直观
  { $sort: { "_id.year": 1, "_id.month": 1, "_id.day": 1 } }
])
.then(results => {
  console.log("完整统计结果:", results);
})
.catch(err => {
  console.error("聚合查询出错:", err);
});

执行后会得到两条结果:

[
  { _id: { year: 2018, month: 3, day: 31 }, count: 1 },
  { _id: { year: 2018, month: 4, day: 1 }, count: 2 }
]

场景2:按日期+状态分组,统计每个日期下不同状态的记录数

如果需要更细粒度的统计,比如每天每个status的数量,可以调整$group的_id包含status字段:

YourModel.aggregate([
  {
    $group: {
      _id: {
        year: { $year: "$createdAt" },
        month: { $month: "$createdAt" },
        day: { $dayOfMonth: "$createdAt" },
        status: "$status"
      },
      count: { $sum: 1 }
    }
  },
  { $sort: { "_id.year": 1, "_id.month": 1, "_id.day": 1, "_id.status": 1 } }
])

结果会包含三条数据,对应每条记录的状态统计:

[
  { _id: { year: 2018, month: 3, day: 31, status: -1 }, count: 1 },
  { _id: { year: 2018, month: 4, day: 1, status: 0 }, count: 1 },
  { _id: { year: 2018, month: 4, day: 1, status: 2 }, count: 1 }
]

场景3:按日期分组,同时统计每个日期下各状态的数量(结构化展示)

如果希望把每个状态的数量作为单独字段展示(比如一条数据包含当天所有状态的统计),可以用$cond结合$sum实现:

YourModel.aggregate([
  {
    $group: {
      _id: {
        year: { $year: "$createdAt" },
        month: { $month: "$createdAt" },
        day: { $dayOfMonth: "$createdAt" }
      },
      totalCount: { $sum: 1 },
      statusMinus1: { $sum: { $cond: [{ $eq: ["$status", -1] }, 1, 0] } },
      status0: { $sum: { $cond: [{ $eq: ["$status", 0] }, 1, 0] } },
      status2: { $sum: { $cond: [{ $eq: ["$status", 2] }, 1, 0] } }
    }
  },
  { $sort: { "_id.year": 1, "_id.month": 1, "_id.day": 1 } }
])

返回的结果会更结构化:

[
  {
    _id: { year: 2018, month: 3, day: 31 },
    totalCount: 1,
    statusMinus1: 1,
    status0: 0,
    status2: 0
  },
  {
    _id: { year: 2018, month: 4, day: 1 },
    totalCount: 2,
    statusMinus1: 0,
    status0: 1,
    status2: 1
  }
]

为什么你之前只得到一条结果?

大概率是这两个原因之一:

  1. $match阶段过滤了数据:检查你的$match条件,是不是不小心排除了3月31日的那条记录(比如时间范围只选了4月1日之后);
  2. 时区问题:MongoDB的日期操作默认使用UTC时间,如果你的业务时间是本地时区,可能导致日期提取错误。可以用$dateToString指定时区来修正,比如:
_id: {
  date: { $dateToString: { format: "%Y-%m-%d", date: "$createdAt", timezone: "Asia/Shanghai" } }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:35:17