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

Express.js如何按公共字段合并多条DB查询记录为结构化数组

Express.js 预售数据维度合并实现方案

问题背景

开发中处理数据库返回的preorder_data预售销售数据集时,同零售点、同路线维度下的记录region/area/house/territory/point/dpid/route/retailer_code/date公共字段值完全一致,仅skid(产品编码)、volume(销量)、value(销售额)字段存在差异。需要将同维度多条记录合并为单条结构:公共字段保留为对象顶层属性,差异化的产品销售信息统一归集到sale_info数组,最终输出符合结构的结果数组。

原始数据集示例

const preorder_data = [
  {
    region: "Rajshahi",
    area: "Bogra",
    house: "Mr Brothers",
    territory: "Bogra 1",
    point: "Bogura",
    skid: 20000007,
    dpid: 221,
    route: "18A",
    retailer_code: "RAJ-38-00526",
    volume: 4,
    value: 5840,
    date: "2022-01-30T18:00:00.000Z",
  },
  {
    region: "Rajshahi",
    area: "Bogra",
    house: "Mr Brothers",
    territory: "Bogra 1",
    point: "Bogura",
    skid: 20000003,
    dpid: 221,
    route: "18A",
    retailer_code: "RAJ-38-00526",
    volume: 5,
    value: 8952,
    date: "2022-01-30T18:00:00.000Z",
  },
  {
    region: "Rajshahi",
    area: "Bogra",
    house: "M/S Sons",
    territory: "Bogra 2",
    point: "Bogura",
    skid: 20000009,
    dpid: 221,
    route: "22B",
    retailer_code: "RAJ-39-85632",
    volume: 4,
    value: 5840,
    date: "2022-01-30T18:00:00.000Z",
  },
  {
    region: "Rajshahi",
    area: "Bogra",
    house: "M/S Sons",
    territory: "Bogra 2",
    point: "Bogura",
    skid: 20000005,
    dpid: 221,
    route: "22B",
    retailer_code: "RAJ-39-85632",
    volume: 5,
    value: 3965,
    date: "2022-01-30T18:00:00.000Z",
  },{
    region: "Rajshahi",
    area: "Bogra",
    house: "M/S Sons",
    territory: "Bogra 2",
    point: "Bogura",
    skid: 20000002,
    dpid: 221,
    route: "22B",
    retailer_code: "RAJ-39-85632",
    volume: 8,
    value: 13366,
    date: "2022-01-30T18:00:00.000Z",
  },
];

预期输出结构

[
  {
    region: 'Rajshahi',
    area: 'Bogra',
    house: 'Mr Brothers',
    territory: 'Bogra 1',
    point: 'Bogura',
    dpid: 221,
    route: '18A',
    retailer_code: 'RAJ-38-00526',
    date: '2022-01-31',
    sale_info :[
      {skid:20000003,volume:5,value:8952},
      {skid:20000007,volume:4,value:5840}
    ]
  },{
    region: "Rajshahi",
    area: "Bogra",
    house: "M/S Sons",
    territory: "Bogra 2",
    point: "Bogura",
    dpid: 221,
    route: "22B",
    retailer_code: "RAJ-39-85632",
    date: '2022-01-31',
    sale_info :[
      {skid:20000002,volume:8,value:13366},
      {skid:20000005,volume:5,value:3965},
      {skid:20000009,volume:4,value:5840}
    ]
  },    
]

原有代码问题

之前编写的forEach逻辑存在3个核心错误,导致无法实现合并效果:

  • 未做分组判断:遍历每条记录时都直接生成新数组推入结果,完全没有同维度记录的合并逻辑
  • 冗余异步声明:forEach回调加了不必要的async关键字,该场景无异步操作,且forEach本身不支持异步等待
  • 结构不符合要求:将公共字段存入数组而非对象顶层,也没有归集skid/volume/value三个差异化字段
    原有错误代码参考:
var final_arr = []; 
preorder_data.forEach(async (val, key) => {
  var temp_arr = [];         
  temp_arr.push(val.region);
  temp_arr.push(val.area);
  temp_arr.push(val.house);
  temp_arr.push(val.territory);
  temp_arr.push(val.point);
  temp_arr.push(val.route);
  temp_arr.push(val.retailer_code);       
  final_arr.push(temp_arr);
});

正确实现代码

核心思路是通过唯一分组key做维度聚合:先提取所有公共字段生成唯一分组标识,用临时对象存储分组结果,遍历原始数据时初始化不存在的分组、追加销售数据到已存在的分组,最后将分组对象的值转为数组即可。

const groupMap = {};
// 定义所有公共字段列表
const COMMON_FIELDS = ['region', 'area', 'house', 'territory', 'point', 'dpid', 'route', 'retailer_code', 'date'];

preorder_data.forEach(item => {
  // 拼接公共字段值生成分组唯一key,用特殊分隔符避免字段值拼接冲突
  const groupKey = COMMON_FIELDS.map(field => item[field]).join('_||_');
  
  // 当前分组不存在时,初始化分组结构
  if (!groupMap[groupKey]) {
    const groupItem = {};
    // 拷贝所有公共字段到分组对象顶层
    COMMON_FIELDS.forEach(field => {
      // 如需格式化date字段(比如转成YYYY-MM-DD格式),可在这里单独判断处理
      if (field === 'date') {
        groupItem[field] = new Date(item[field]).toISOString().split('T')[0];
      } else {
        groupItem[field] = item[field];
      }
    });
    // 初始化销售信息空数组
    groupItem.sale_info = [];
    groupMap[groupKey] = groupItem;
  }

  // 将当前记录的差异化销售数据推入对应分组的sale_info数组
  groupMap[groupKey].sale_info.push({
    skid: item.skid,
    volume: item.volume,
    value: item.value
  });
});

// 取出分组映射的所有值,得到最终结果数组
const final_arr = Object.values(groupMap);

补充说明

  • 分组key拼接时使用_||_这类特殊分隔符,是为了避免不同字段值拼接后产生相同字符串导致分组错误
  • 如果需要对sale_info内的产品做排序,可在生成final_arr前遍历每个分组的sale_info数组调用sort方法
  • 如果公共字段后续有增减,只需要修改COMMON_FIELDS数组即可,无需改动核心遍历逻辑

内容的提问来源于stack exchange,提问作者Jone D Adam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 02:46:12