You need to enable JavaScript to run this app. Nodejs 如何按指定时间单位对带时间戳的大数组对象分组聚合
优惠活动
大模型
产品
解决方案
定价
更多

Nodejs 如何按指定时间单位对带时间戳的大数组对象分组聚合

大数据量时间分组&聚合实现方案

前置说明

针对20万~100万级的时间序列数据,推荐先做时间戳预处理,避免重复解析时间字符串,减少性能损耗。

第一步:定义时间粒度配置

const TIME_GRANULARITY = {
  '1min': 60000,
  '5min': 300000,
  '15min': 900000,
  '1hour': 3600000
}

方案一:按时间范围输出嵌套分组数组

实现逻辑

  1. 先把所有数据的localcol转成毫秒时间戳,同时拿到整个数据集的最小时间戳作为分组起始基准
  2. 计算每条数据所属的分组下标:分组下标 = Math.floor((当前数据时间戳 - 最小时间戳) / 选中的时间粒度毫秒数)
  3. 按下标把数据放到对应子数组里即可

代码实现

function groupByTime(rawData, granularity) {
  // 预处理所有数据转时间戳,同时找最小时间
  const processed = rawData.map(item => {
    const ts = new Date(item.localcol).getTime()
    return { ...item, ts }
  })
  const minTs = Math.min(...processed.map(i => i.ts))
  const unit = TIME_GRANULARITY[granularity]
  const groups = []
  processed.forEach(item => {
    const groupIndex = Math.floor((item.ts - minTs) / unit)
    if (!groups[groupIndex]) {
      // 子数组第一个元素是时间范围,后面是对应数据
      const start = minTs + groupIndex * unit
      groups[groupIndex] = [[start, start + unit]]
    }
    groups[groupIndex].push(item)
  })
  // 过滤时间断层产生的空分组
  return groups.filter(Boolean)
}

方案二:直接输出带平均值的聚合结果

实现逻辑

分组逻辑和方案一一致,只是每个分组存储计数和各字段累加值,最后直接计算平均值,无需后续二次遍历,性能更高

代码实现

function aggregateByTime(rawData, granularity) {
  const processed = rawData.map(item => {
    const ts = new Date(item.localcol).getTime()
    return { ...item, ts }
  })
  const minTs = Math.min(...processed.map(i => i.ts))
  const unit = TIME_GRANULARITY[granularity]
  const aggMap = new Map()
  processed.forEach(item => {
    const groupIndex = Math.floor((item.ts - minTs) / unit)
    if (!aggMap.has(groupIndex)) {
      const start = minTs + groupIndex * unit
      aggMap.set(groupIndex, {
        timeRange: [start, start + unit],
        count: 0,
        datamapSum: {
          Curr1_mA: 0,
          Curr2_mA: 0,
          Curr3_mA: 0,
          P1_W: 0,
          P2_W: 0,
          P3_W: 0,
          P_Total_W: 0,
          U1N_Vx10: 0,
          U2N_Vx10: 0,
          U3N_Vx10: 0
        }
      })
    }
    const group = aggMap.get(groupIndex)
    group.count += 1
    Object.keys(group.datamapSum).forEach(key => {
      group.datamapSum[key] += item.datamap[key]
    })
  })
  // 转换为结果数组并计算平均值
  return Array.from(aggMap.values()).map(group => ({
    timeRange: group.timeRange,
    datamapAvg: Object.fromEntries(
      Object.entries(group.datamapSum).map(([k, v]) => [k, v / group.count])
    )
  }))
}

性能优化提示

  • 100万条数据在Node.js/现代浏览器中运行无压力,总耗时一般在100ms以内
  • 如果数据本身已经按时间升序排列,可以省略查找最小时间戳的步骤,直接用第一条数据的时间戳作为基准,性能还能再提升30%左右
  • 不需要保留原始数据的场景优先使用方案二,内存占用仅为方案一的1/10左右

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 03:45:03