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

MongoDB按独立日期范围聚合子字段,实现多时间维度统计的方法

MongoDB聚合查询:按多日期范围统计各Action的总和

你完全不需要依赖mapReduce!用MongoDB的聚合管道就能轻松实现你想要的效果,而且效率更高。我来帮你调整查询逻辑,实现按全时段、最近7/30/90天统计每个action的总和,并且输出你期望的结构。

核心思路

  1. 先定位目标_id的文档(把$match放在最前面,减少后续处理的数据量)
  2. 计算出各个日期范围的阈值(比如7天前的日期)
  3. 对每个action数组,分别筛选不同日期范围的元素并求和
  4. 最后重新组织输出结构,匹配你想要的格式

完整聚合查询语句

db.collection.aggregate([
  // 第一步:先筛选目标文档,减少后续处理量
  { $match: { _id: "12345678" } },
  // 第二步:计算各个日期范围的阈值(若date已是ISODate,可跳过后续的$dateFromString转换)
  { $addFields: {
      last7DaysDate: { $subtract: [new Date(), 7*24*60*60*1000] },
      last30DaysDate: { $subtract: [new Date(), 30*24*60*60*1000] },
      last90DaysDate: { $subtract: [new Date(), 90*24*60*60*1000] }
    }
  },
  // 第三步:对每个action计算各时间段的总和
  { $addFields: {
      // 处理action1
      action1_stats: {
        alltime: { $sum: "$action1.value" },
        last7Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action1",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last7DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        },
        last30Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action1",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last30DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        },
        last90Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action1",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last90DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        }
      },
      // 处理action2,逻辑与action1一致
      action2_stats: {
        alltime: { $sum: "$action2.value" },
        last7Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action2",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last7DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        },
        last30Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action2",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last30DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        },
        last90Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action2",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last90DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        }
      },
      // 处理action3,逻辑与action1一致
      action3_stats: {
        alltime: { $sum: "$action3.value" },
        last7Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action3",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last7DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        },
        last30Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action3",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last30DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        },
        last90Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action3",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last90DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        }
      },
      // 处理action4,逻辑与action1一致
      action4_stats: {
        alltime: { $sum: "$action4.value" },
        last7Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action4",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last7DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        },
        last30Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action4",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last30DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        },
        last90Days: {
          $sum: {
            $map: {
              input: { $filter: {
                  input: "$action4",
                  cond: { $gte: [ { $dateFromString: { dateString: "$$this.date" } }, "$last90DaysDate" ] }
                }
              },
              as: "item",
              in: "$$item.value"
            }
          }
        }
      }
    }
  },
  // 第四步:重新组织输出结构,匹配你想要的格式
  { $project: {
      _id: 1,
      action1: "$action1_stats",
      action2: "$action2_stats",
      action3: "$action3_stats",
      action4: "$action4_stats",
      // 移除临时生成的日期阈值字段
      last7DaysDate: 0,
      last30DaysDate: 0,
      last90DaysDate: 0
    }
  }
])

关键细节说明

  1. 日期类型转换:因为你的date字段是字符串格式,所以用$dateFromString将其转换为MongoDB可识别的日期类型,才能和计算出的日期阈值正确比较。如果你的date已是ISODate类型,可以直接去掉$dateFromString,用$$this.date直接比较。
  2. $match的位置:将$match放在聚合管道最开头,先过滤出目标文档,避免处理无关数据,大幅提升查询效率。
  3. 复用计算结果:通过$addFields只计算一次日期阈值,后续所有action的筛选都复用这些值,避免重复计算。
  4. 筛选求和逻辑:先用$filter筛选符合日期范围的元素,再用$map提取元素的value,最后用$sum求和,实现各时间段的统计。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:43:13