NodeJS中使用Sequelize实现三表关联及解决Report未定义报错
问题根源
- 所有字段名未加引号:Sequelize关联配置的
foreignKey、targetKey以及查询的attributes接收的是字段名字符串,你直接写Report、id等未加引号,JS会将其识别为未声明的变量,直接触发未定义报错。 - 关联关系逻辑写反:
hasMany的外键是子表中存储父表主键的字段,targetKey是父表的主键字段,你之前的配置完全搞反了两者的对应关系。 - 关联层级错误:你的查询是多表跨中间表关联,需要嵌套配置
include,不能平级引入tblHeadings和tblAccess。
正确关联配置
const sequelize = DB.GetDB(DB.reports); const rptDB = rpts.initModels(sequelize); // 提前引入操作符 const { Op } = require('sequelize'); // 1. tblReports 和 中间表tblReportHeadings的关联 // tblReports的id对应tblReportHeadings的Report字段 rptDB.tblReports.hasMany(rptDB.tblReportHeadings, { foreignKey: 'Report', // 子表(tblReportHeadings)里的外键字段 targetKey: 'id' // 父表(tblReports)里的关联主键 }); rptDB.tblReportHeadings.belongsTo(rptDB.tblReports, { foreignKey: 'Report', // 当前表(tblReportHeadings)的外键字段 targetKey: 'id' // 关联父表(tblReports)的主键 }); // 2. tblHeadings 和 中间表tblReportHeadings的关联 // tblHeadings的id对应tblReportHeadings的Heading字段 rptDB.tblHeadings.hasMany(rptDB.tblReportHeadings, { foreignKey: 'Heading', targetKey: 'id' }); rptDB.tblReportHeadings.belongsTo(rptDB.tblHeadings, { foreignKey: 'Heading', targetKey: 'id' }); // 3. tblHeadings 和 tblAccess的关联 // tblHeadings的id对应tblAccess的Heading字段 rptDB.tblHeadings.hasMany(rptDB.tblAccess, { foreignKey: 'Heading', targetKey: 'id' }); rptDB.tblAccess.belongsTo(rptDB.tblHeadings, { foreignKey: 'Heading', targetKey: 'id' });
正确查询代码
let ret = await rptDB.tblReports.findAll({ attributes: ['id', 'reportTitle'], distinct: true, // 对应SQL的DISTINCT include: [ { model: rptDB.tblReportHeadings, attributes: [], // 不需要返回中间表字段就设为空数组 include: [ { model: rptDB.tblHeadings, attributes: ['Heading'], include: [ { model: rptDB.tblAccess, attributes: [], where: sequelize.where(sequelize.fn('LOWER', sequelize.col('accessLevel')), { [Op.in]: roles.map(r => r.toLowerCase()) // 对应WHERE LOWER(accessLevel) IN逻辑 }) } ] } ] } ], order: [['reportTitle', 'ASC']], // 对应ORDER BY排序逻辑 logging: (sql) => console.log(sql) });
内容的提问来源于stack exchange,提问作者Geoff
相关产品推荐
相关产品推荐

