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

如何在MongoDB中按月度日期排序集合并生成含数据的月度日期聚合数组

MongoDB聚合管道实现指定月份每日支出统计

要实现生成指定月份的每日支出数组(包含当月所有日期,无支出日期对应空数组),可以通过以下聚合管道完成:

核心思路

  1. 筛选目标月份的支出数据
  2. 按日期分组,归集每天的支出记录
  3. 生成当月所有日期的完整序列
  4. 将完整日期序列与分组后的支出数据做左连接,补全无支出日期的空数组

完整聚合管道代码

db.expenses.aggregate([
  // 筛选2023年10月的支出(按需修改日期范围)
  {
    $match: {
      createdAt: {
        $gte: ISODate("2023-10-01T00:00:00Z"),
        $lt: ISODate("2023-11-01T00:00:00Z")
      }
    }
  },
  // 按日分组,收集当天所有支出
  {
    $group: {
      _id: { $dateToString: { format: "%d", date: "$createdAt" } },
      expenses: { 
        $push: { 
          title: "$title", 
          value: "$value", 
          createdAt: { $dateToString: { format: "%Y-%m-%dT%H:%M:%S.%LZ", date: "$createdAt" } } 
        } 
      }
    }
  },
  // 聚合所有分组数据,同时计算当月总天数
  {
    $group: {
      _id: null,
      dailyExpenses: { $push: { day: "$_id", expenses: "$expenses" } },
      monthDays: { $max: { $dayOfMonth: ISODate("2023-10-01T00:00:00Z") } }
    }
  },
  // 生成当月所有日期的两位数字符串(如'01'、'15')
  {
    $project: {
      _id: 0,
      dailyExpenses: 1,
      allDays: {
        $map: {
          input: { $range: [1, { $add: ["$monthDays", 1] }] },
          as: "dayNum",
          in: {
            $cond: [
              { $lt: ["$$dayNum", 10] },
              { $concat: ["0", { $toString: "$$dayNum" }] },
              { $toString: "$$dayNum" }
            ]
          }
        }
      }
    }
  },
  // 匹配日期与支出数据,无支出则返回空数组
  {
    $project: {
      result: {
        $map: {
          input: "$allDays",
          as: "day",
          in: {
            day: "$$day",
            expenses: {
              $ifNull: [
                { $arrayElemAt: ["$dailyExpenses.expenses", { $indexOfArray: ["$dailyExpenses.day", "$$day"] }] },
                []
              ]
            }
          }
        }
      }
    }
  },
  // 输出最终结果数组
  {
    $replaceRoot: { newRoot: "$result" }
  }
])

关键细节说明

  • 日期筛选:用$gte当月第一天、$lt下月第一天的方式,避免时区转换导致的日期偏差。
  • 日期格式化:通过$dateToString将日期转为两位日份字符串,保证和生成的日期序列格式一致。
  • 空数组补全:利用$indexOfArray查找对应日期的支出数据,找不到时用$ifNull返回空数组,确保每个日期都有对应的记录。

如果需要动态指定月份,只需修改$match和monthDays计算中的日期参数即可,比如从应用层传入目标月份的起始日期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 15:39:52