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

如何从MySQL查询结果生成嵌套对象?(Node.js/React场景)

问题描述

我通过Node.js从MySQL查询获取了如下模拟数据集:

id  date (y/m/d)  value
 1  2022-1-1      random value
 2  2022-2-5      random value
 3  2022-3-3      random value
 4  2022-4-6      random value
 5  2022-5-11     random value
 6  2022-6-7      random value
 7  2022-7-16     random value
 8  2022-8-4      random value
 9  2022-9-7      random value
10  2022-10-8     random value
11  2022-11-4     random value
12  2022-12-9     random value
13  2023-1-2      random value
14  2023-2-4      random value
15  2023-3-22     random value
16  2023-4-5      random value
17  2023-5-8      random value
18  2023-6-19     random value
19  2023-7-12     random value
20  2023-8-4      random value
21  2023-9-2      random value
22  2023-10-10    random value
23  2023-11-21    random value
24  2023-12-27    random value

需要将其转换为如下按年、月、日层级嵌套的对象结构,用于React前端展示:

[{
    year:2022,
    value:[
        {
            month:1,
            value:[
                {
                    day:1,
                    value:'random value'
                }
            ]
        },
        {
            month:2,
            value:[
                {
                    day:5,
                    value:'random value'
                }
            ],
            ...
        }
    ]
},{
    year:2023,
    value:[
        ...
    ]
}]

该操作会在服务器上多次执行,因此需要高效、低开销的实现方案,请问有什么解决思路?

高效实现思路

1. 哈希映射快速定位层级,一次遍历完成分组

用Map对象记录已创建的年份、月份节点,遍历原始数据时直接定位到对应层级插入,避免重复遍历结果数组查找,时间复杂度为O(n),是最高效的分组方式:

function transformData(rawData) {
    const yearMap = new Map();
    const result = [];

    for (const item of rawData) {
        // 若数据库已拆分年/月/日,可直接使用对应字段,跳过字符串解析
        const [year, month, day] = item.date.split('-').map(Number);
        const itemValue = item.value;

        // 处理年份节点
        let yearNode = yearMap.get(year);
        if (!yearNode) {
            yearNode = { year, value: [] };
            yearMap.set(year, yearNode);
            result.push(yearNode);
        }

        // 处理月份节点,在年份节点内维护临时Map
        let monthMap = yearNode._monthMap;
        if (!monthMap) {
            monthMap = new Map();
            yearNode._monthMap = monthMap;
        }
        let monthNode = monthMap.get(month);
        if (!monthNode) {
            monthNode = { month, value: [] };
            monthMap.set(month, monthNode);
            yearNode.value.push(monthNode);
        }

        // 插入当日数据
        monthNode.value.push({ day, value: itemValue });
    }

    // 清理临时存储的_monthMap字段
    result.forEach(node => delete node._monthMap);
    return result;
}

2. 数据库层面提前优化,降低后端处理成本

  • 直接拆分日期字段:在MySQL查询中用内置函数提取年、月、日,返回数字类型,避免后端做字符串解析:
    SELECT 
      id, 
      YEAR(date_column) AS year, 
      MONTH(date_column) AS month, 
      DAY(date_column) AS day, 
      value 
    FROM your_table 
    ORDER BY date_column;
    
  • 按日期排序:查询时加上ORDER BY,确保数据按时间顺序返回,分组后层级内的月份、日期自然有序,无需额外排序。

3. 优化内存与执行效率

  • 避免在循环内创建重复对象或函数,保持逻辑极简;
  • 数据量极大时,使用MySQL流式查询(如mysql2库的stream()方法),边读数据边分组,避免一次性加载全量数据到内存。

4. 缓存复用结果(数据更新频率低时适用)

如果数据不是实时更新,可将转换后的嵌套对象缓存到内存或Redis中,相同请求直接返回缓存结果,彻底避免重复执行转换逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:40:34