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

MongoDB按date、hour分组统计唯一sessionId数量的查询请求

解决方案:MongoDB按日期+小时统计唯一会话数

没问题,我帮你写出完全匹配需求的MongoDB聚合查询,分为两种场景供你选择:

场景1:只统计存在数据的小时(无数据的小时不显示)

这个版本会直接根据你集合中存在的date和hour分组统计,没有记录的小时不会出现在结果中:

db.yourCollectionName.aggregate([
  // 按日期和小时分组,统计该组内唯一sessionId的数量
  {
    $group: {
      _id: {
        date: "$date",
        hour: "$hour"
      },
      uniqueSessions: { $size: { $addToSet: "$sessionId" } }
    }
  },
  // 按日期聚合,整理每个日期下的小时统计数据为键值对数组
  {
    $group: {
      _id: "$_id.date",
      hourData: {
        $push: {
          k: "$_id.hour",
          v: "$uniqueSessions"
        }
      }
    }
  },
  // 将日期作为键,小时统计对象作为值,生成键值对结构
  {
    $project: {
      _id: 0,
      data: {
        k: "$_id",
        v: { $arrayToObject: "$hourData" }
      }
    }
  },
  // 转换为最终的对象格式输出
  {
    $replaceRoot: {
      newRoot: { $arrayToObject: "$data" }
    }
  }
])

场景2:补全所有24小时(无数据的小时显示0)

如果需要像你示例中那样,即使某个小时没有会话记录也显示0,可以用这个版本,会自动补全00-23所有小时:

db.yourCollectionName.aggregate([
  // 基础统计:按日期+小时统计唯一会话数
  {
    $group: {
      _id: {
        date: "$date",
        hour: "$hour"
      },
      uniqueSessions: { $size: { $addToSet: "$sessionId" } }
    }
  },
  // 按日期聚合,收集该日期下的所有小时统计数据
  {
    $group: {
      _id: "$_id.date",
      stats: {
        $push: {
          hour: "$_id.hour",
          count: "$uniqueSessions"
        }
      }
    }
  },
  // 生成0-23的数字小时数组
  {
    $addFields: {
      allHours: { $range: [0, 24] }
    }
  },
  // 将数字小时转换为两位字符串格式(比如0→"00",5→"05")
  {
    $addFields: {
      allHours: {
        $map: {
          input: "$allHours",
          as: "h",
          in: {
            $toString: {
              $concat: [
                { $substr: ["0", 0, { $subtract: [2, { $strLenCP: { $toString: "$$h" } }] }] },
                { $toString: "$$h" }
              ]
            }
          }
        }
      }
    }
  },
  // 左连接所有小时和统计数据,无数据的小时填充为0
  {
    $addFields: {
      hourData: {
        $map: {
          input: "$allHours",
          as: "hour",
          in: {
            k: "$$hour",
            v: {
              $ifNull: [
                { $arrayElemAt: ["$stats.count", { $indexOfArray: ["$stats.hour", "$$hour"] }] },
                0
              ]
            }
          }
        }
      }
    }
  },
  // 构建日期到小时统计对象的键值对
  {
    $project: {
      _id: 0,
      data: {
        k: "$_id",
        v: { $arrayToObject: "$hourData" }
      }
    }
  },
  // 转换为最终的目标格式
  {
    $replaceRoot: {
      newRoot: { $arrayToObject: "$data" }
    }
  }
])

关键步骤说明

  • $addToSet + $size:确保统计的是唯一的sessionId数量,而不是该小时内的总记录数。
  • $arrayToObject:将数组形式的键值对转换为对象结构,完美匹配你需要的输出格式。
  • 场景2中的$range和$map:用于生成并格式化所有24小时,保证结果的完整性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 22:58:13