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

Sequelize外键关联问题:如何将关联字段展平为顶层属性

解决方案

咱们一步步来解决你的问题,先理清楚关联关系的合理性,再调整查询结构得到你想要的返回格式:

1. 修正关联关系(更符合业务逻辑)

你当前用hasOne关联skillsets和ratings,但从业务场景看,一个技能应该可以对应多个员工的评分(不同empID的ratings记录),所以更合适的关联是hasMany而非hasOne。同时检查字段映射是否匹配:

// 修正后的关联定义
skillsets.hasMany(ratings, { 
  foreignKey: 'skillID', 
  sourceKey: 'skillsetID' // 确保skillsets模型的skillsetID对应数据库的skill_id字段
});
ratings.belongsTo(skillsets, { 
  foreignKey: 'skillID', 
  targetKey: 'skillsetID' 
});

如果你的业务确实是一个技能对应某员工的唯一评分,hasOne也能运行,但hasMany更通用,不会限制后续扩展。

2. 调整查询得到期望的返回格式

现在返回的rating是嵌套对象,要直接变成数值,有两种实用方案:

方案一:通过Sequelize查询直接映射字段

在findAll中,直接将关联表的rating字段映射为主模型的属性,同时隐藏关联模型的冗余属性,并开启raw: true返回平面对象:

const result = await skillsets.findAll({
  where: { roleID: role },
  attributes: [
    'skillsetID',
    'roleID',
    'field',
    'skillName',
    // 把关联表的rating字段映射为当前对象的rating属性
    [sequelize.col('rating.rating'), 'rating']
  ],
  include: [{
    model: ratings,
    where: { empID: empID }, // 这里用模型属性名empID,而非数据库字段emp_id,更符合规范
    attributes: [], // 不返回关联模型的其他属性
    required: false
  }],
  raw: true // 返回平面对象,而非Sequelize模型实例
});

这样生成的SQL会直接把rating.rating作为rating列返回,结果就是你期望的结构,rating是数值类型。

方案二:查询后手动转换结果格式

如果不想修改查询结构,可以在查询完成后,用map函数调整返回格式:

const results = await skillsets.findAll({
  where: { roleID: role },
  include: [{
    model: ratings,
    where: { empID: empID },
    attributes: ['rating'],
    required: false
  }]
});

// 转换为目标格式
const formattedResults = results.map(item => {
  // 先把模型实例转为普通对象
  const plainItem = item.get({ plain: true });
  return {
    ...plainItem,
    // 有评分则取数值,否则设为null,parseInt转换为数字类型
    rating: plainItem.rating ? parseInt(plainItem.rating.rating) : null
  };
});

额外小提示

你查询里的where:{ emp_id: empID }建议改成where:{ empID: empID },因为模型里的属性名是empID(对应数据库字段emp_id),用模型属性名更符合Sequelize的设计规范,避免硬编码数据库字段名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:46:44