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

在MongoDB中不使用$accumulator和自定义JS函数计算最长连胜

获取MongoDB中最长连胜记录(无JS依赖方案)

针对你提供的文档集合,以下是完全依赖MongoDB原生聚合操作符的解决方案,无需自定义JS函数:

完整聚合管道

db.collection.aggregate([
  // 1. 按时间顺序排序,确保连胜按发生顺序统计
  { $sort: { createdAt: 1 } },
  
  // 2. 用窗口函数标记连胜分组:同一连胜的文档分配相同group_id
  {
    $setWindowFields: {
      partitionBy: null, // 全局窗口,所有文档在同一分区
      sortBy: { createdAt: 1 },
      output: {
        group_id: {
          $sum: {
            $cond: [
              // 首次文档或当前win与前一个不同时,分组ID+1
              { $or: [ { $eq: [ { $lag: "$win" }, null ] }, { $ne: [ "$win", { $lag: "$win" } ] } ] },
              1,
              0
            ]
          }
        }
      }
    }
  },
  
  // 3. 按分组ID聚合,统计每组文档数量(即连胜长度),保留win状态
  {
    $group: {
      _id: { group_id: "$group_id", win: "$win" },
      streak_length: { $count: {} }
    }
  },
  
  // 4. 仅保留胜利的连胜记录
  { $match: { "_id.win": true } },
  
  // 5. 取最长连胜长度,无胜利则返回0
  {
    $group: {
      _id: null,
      max_win_streak: { $max: "$streak_length" }
    }
  },
  { $project: { _id: 0, max_win_streak: { $ifNull: [ "$max_win_streak", 0 ] } } }
])

各阶段说明

  • $sort:必须按createdAt升序排列,保证连胜统计的时间顺序,避免分组错乱。
  • $setWindowFields:通过$lag获取前一个文档的win值,用$cond判断是否开启新连胜组,再用$sum生成唯一group_id——同一连胜序列的文档会拥有相同group_id。
  • $group(第一次):按group_id和win分组,用$count统计每组长度,得到每个连胜序列的持续次数。
  • $match:过滤掉失败的连胜记录,只保留胜利相关的统计结果。
  • $group(第二次):全局聚合取最大连胜长度,用$ifNull处理无胜利记录的边界情况,返回0。

针对你提供的示例数据,执行后会返回{ "max_win_streak": 2 },符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 03:52:24