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

Node.js处理MySQL关联查询结果,构建嵌套JSON结构问题

问题分析与解决方案

核心原因排查

  • 字段名冲突:LEFT JOIN时多表存在同名字段(如Id),MySQL会自动覆盖后续字段值,导致你获取的Category.Id被覆盖为其他表的Id或直接返回undefined。
  • 大小写/字段映射不匹配:数据库字段是下划线命名(如category_id)或大小写格式(如CategoryID),但代码里用了错误的属性名(如Category.Id)访问。
  • 遍历逻辑漏洞:构建嵌套结构时,未正确判断数组中已存在的分类,导致每次循环都新建分类对象,造成重复。

具体解决步骤

1. 修正SQL查询的字段别名

给查询结果的分类字段添加唯一别名,彻底避免字段冲突:

SELECT 
  pc.Id AS category_id,
  pc.Name AS category_name,
  ps.Id AS skill_id,
  ps.Name AS skill_name,
  pm.Content AS message_content
FROM Progress_Category pc
LEFT JOIN Progress_Skill ps ON pc.Id = ps.CategoryId
LEFT JOIN Progress_Message pm ON ps.Id = pm.SkillId

2. 调整Node.js代码的属性访问逻辑

根据查询结果的实际字段名,正确访问属性并构建嵌套结构:

// 假设flatResults是你的查询返回结果
const nestedCategories = [];

flatResults.forEach(row => {
  // 查找当前分类是否已存在于数组中
  let targetCategory = nestedCategories.find(cat => cat.id === row.category_id);
  
  if (!targetCategory) {
    // 不存在则创建新分类对象并推入数组
    targetCategory = {
      id: row.category_id,
      name: row.category_name,
      skills: []
    };
    nestedCategories.push(targetCategory);
  }
  
  // 处理技能数据(避免空技能重复添加)
  if (row.skill_id) {
    let targetSkill = targetCategory.skills.find(skill => skill.id === row.skill_id);
    if (!targetSkill) {
      targetSkill = {
        id: row.skill_id,
        name: row.skill_name,
        messages: row.message_content ? [row.message_content] : []
      };
      targetCategory.skills.push(targetSkill);
    } else {
      // 追加消息(避免重复消息)
      if (row.message_content && !targetSkill.messages.includes(row.message_content)) {
        targetSkill.messages.push(row.message_content);
      }
    }
  }
});

3. 验证字段映射一致性

如果使用ORM(如Sequelize),需确保模型字段与数据库字段映射正确:

// Sequelize模型示例:匹配数据库的大小写/下划线字段
const ProgressCategory = sequelize.define('Progress_Category', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    field: 'Id' // 对应数据库的大写Id字段
  },
  name: {
    type: DataTypes.STRING,
    field: 'Name'
  }
});

4. 快速调试方法

遍历前打印第一条结果,确认返回的字段名和值是否符合预期:

console.log('查询结果示例:', flatResults[0]);
// 输出示例:{ category_id: 1, category_name: '前端开发', skill_id: 2, ... }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:24:45