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

如何使用Mongoose在MongoDB中按天统计近一周的平均值?

用Mongoose实现过去7天每日value平均值统计

当然可以直接通过Mongoose结合MongoDB的聚合框架搞定这个需求!核心思路是利用聚合管道完成时间范围筛选、按天分组求均值、填充缺失日期、排序生成目标数组这几个步骤,完全不需要在应用层做额外的数据拼接处理。

核心实现步骤

  1. 筛选时间范围:先确定今日往前推7天的时间区间,只处理这个范围内的文档。
  2. 按天分组求均值:将created_at截断到“天”维度,按日期分组计算每天value的平均值。
  3. 填充缺失日期:如果某一天没有数据,要确保结果数组里对应位置有默认值(比如0),这里通过生成7天的日期序列并左连接分组结果来实现。
  4. 排序并生成目标数组:按日期从早到晚(上周同一天到今日)排序,最后提取平均值组成数组。

完整代码示例

假设你的Mongoose模型名为Reading,集合名为readings,可以这样写:

const Reading = require('./models/reading'); // 替换成你的模型路径

async function getWeeklyDailyAverages() {
  const today = new Date();
  // 计算一周前的时间点
  const oneWeekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);

  const result = await Reading.aggregate([
    // 1. 筛选过去7天内的数据
    {
      $match: {
        created_at: {
          $gte: oneWeekAgo,
          $lte: today
        }
      }
    },
    // 2. 按天分组,计算每日平均值
    {
      $group: {
        _id: {
          $dateTrunc: {
            date: "$created_at",
            unit: "day",
            timezone: "Asia/Shanghai" // 务必根据你的业务时区调整
          }
        },
        avgValue: { $avg: "$value" }
      }
    },
    // 3. 生成过去7天的完整日期序列(用来填充无数据的日期)
    {
      $lookup: {
        from: "readings", // 替换成你的集合名称
        let: {},
        pipeline: [
          { $documents: [{ $range: [0, 7] }] },
          { $unwind: "$range" },
          {
            $project: {
              date: {
                $dateSubtract: {
                  startDate: today,
                  unit: "day",
                  amount: { $subtract: [6, "$range"] }
                  // 逻辑:比如今天是周一,6天前是上周周一,0天前是今日,正好覆盖7天
                }
              },
              _id: 0
            }
          },
          {
            $dateTrunc: {
              date: "$date",
              unit: "day",
              timezone: "Asia/Shanghai"
            }
          }
        ],
        as: "dateSeries"
      }
    },
    // 4. 展开日期序列,左连接分组结果
    { $unwind: "$dateSeries" },
    {
      $group: {
        _id: "$dateSeries",
        avgValue: { $first: { $ifNull: ["$avgValue", 0] } } // 无数据时填充0,可换成null
      }
    },
    // 5. 按日期升序排序(从上周同一天到今日)
    { $sort: { _id: 1 } },
    // 6. 将平均值收集成数组
    {
      $group: {
        _id: null,
        dailyAverages: { $push: "$avgValue" }
      }
    },
    // 7. 只保留目标数组字段
    { $project: { _id: 0, dailyAverages: 1 } }
  ]);

  // 返回结果数组,比如[15.2, 16.0, 14.8, ...]
  return result[0]?.dailyAverages || [];
}

// 调用示例
getWeeklyDailyAverages().then(averages => console.log(averages));

注意事项

  • 时区问题:MongoDB默认存储UTC时间,一定要在$dateTrunc或$dateToString中指定业务时区,否则会出现日期截断错误(比如国内业务用Asia/Shanghai)。
  • 兼容旧版本MongoDB:如果你的MongoDB版本低于5.0(不支持$dateTrunc),可以用$dateToString替代:
    _id: {
      $dateToString: {
        format: "%Y-%m-%d",
        date: "$created_at",
        timezone: "Asia/Shanghai"
      }
    }
    
  • 缺失值处理:代码中用0填充无数据的日期,你可以根据需求改成null或者其他默认值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:06:45