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

MongoDB聚合查询实现今日与昨日数据统计及增长率计算

MongoDB聚合查询实现今日与昨日数据统计及增长率计算

嗨,我来帮你搞定这个MongoDB聚合统计的需求!你想要在一次查询里拿到今日和昨日的记录数,进而计算增长率,这个完全可以通过MongoDB的聚合框架实现,我给你一步步拆解:

第一步:明确时间范围计算

首先得确定今日和昨日的时间边界,这里要注意MongoDB的ISODate是UTC时间,如果你的业务时区和UTC不同,记得调整偏移量。以你示例里的今日ISODate("2023-04-02T20:24:18.779Z")为例:

  • 今日起始时间(startOfToday):ISODate("2023-04-02T00:00:00.000Z")
  • 今日结束时间(endOfToday):ISODate("2023-04-02T23:59:59.999Z")
  • 昨日起始时间(startOfYesterday):ISODate("2023-04-01T00:00:00.000Z")
  • 昨日结束时间(endOfYesterday):ISODate("2023-04-01T23:59:59.999Z")

你也可以用MongoDB的日期操作符在聚合内动态计算,比如用$currentDate获取当前时间,再用$dateTrunc截断到日期,然后加减一天来得到昨日的范围,这样就不用在应用层硬编码时间了。

第二步:编写聚合管道

我给你写一个完整的聚合查询,针对你的示例数据,运行后能直接拿到今日和昨日的统计数:

// 先在应用层计算时间范围(或者用聚合内动态计算)
const today = new Date("2023-04-02T20:24:18.779Z");
const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate());
const endOfToday = new Date(startOfToday);
endOfToday.setDate(endOfToday.getDate() + 1);

const startOfYesterday = new Date(startOfToday);
startOfYesterday.setDate(startOfYesterday.getDate() - 1);
const endOfYesterday = startOfToday;

// 聚合查询
db.collection.aggregate([
  // 第一步:过滤出今日和昨日的数据,减少后续处理量
  {
    $match: {
      created_at: {
        $gte: startOfYesterday,
        $lt: endOfToday // 用$lt代替$lte,避免边界时间重复统计
      }
    }
  },
  // 第二步:按日期分组,统计每日的记录数
  {
    $group: {
      _id: {
        $dateToString: { format: "%Y-%m-%d", date: "$created_at" }
      },
      count: { $sum: 1 }
    }
  },
  // 第三步:把分组结果转成键值对,方便后续提取
  {
    $project: {
      _id: 0,
      date: "$_id",
      count: 1
    }
  },
  // 第四步:将结果整理成包含today和yesterday的数组结构
  {
    $group: {
      _id: null,
      createdAt: {
        $push: {
          $cond: [
            { $eq: ["$date", startOfToday.toISOString().split('T')[0]] },
            { today: "$count" },
            { yesterday: "$count" }
          ]
        }
      }
    }
  },
  // 可选:如果只需要统计结果,去掉_id字段
  {
    $project: {
      _id: 0
    }
  }
])

第三步:查询结果说明

针对你的示例数据,运行这个聚合后会得到你想要的结果:

{
  "createdAt": [
    { "today": 3 },
    { "yesterday": 2 }
  ]
}

如果你想把结果合并成单个对象方便取值,也可以把最后两个阶段替换成:

{
  $group: {
    _id: null,
    today: { $max: { $cond: [{ $eq: ["$date", startOfToday.toISOString().split('T')[0]] }, "$count", 0] } },
    yesterday: { $max: { $cond: [{ $eq: ["$date", startOfYesterday.toISOString().split('T')[0]] }, "$count", 0] } }
  }
},
{ $project: { _id: 0 } }

这样会得到更简洁的结构:

{ "today": 3, "yesterday": 2 }

第四步:计算增长率

拿到统计数后,你就可以直接计算增长率了,公式就是你提到的:

const growthRate = ((todayCount - yesterdayCount) / yesterdayCount) * 100;

⚠️ 注意:如果昨日的记录数是0,这里会出现除以0的错误,记得在代码里做判断处理哦!

额外小贴士

如果想在聚合内直接计算增长率,可以在最后加一个$project阶段:

{
  $project: {
    today: 1,
    yesterday: 1,
    growthRate: {
      $cond: [
        { $eq: ["$yesterday", 0] },
        null, // 或者你想要的默认值,比如0或者"Infinite"
        { $multiply: [{ $divide: [{ $subtract: ["$today", "$yesterday"] }, "$yesterday"] }, 100] }
      ]
    }
  }
}

这样就能直接在查询结果里拿到增长率啦!

备注:内容来源于stack exchange,提问作者Emmanuella

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 09:34:59