使用Sequelize findAll()关联查询时抛出TypeError错误求助
问题:Sequelize一对多关联查询嵌套格式异常及报错处理
需求说明
现有invoices表和invoice_items表,为一对多关系(一个invoice对应多个invoice_item),期望通过findAll查询返回如下格式:
[ { name: 'invoice1', invoiceItems: [itemOne, itemTwo] }, ... ]
报错场景及代码
使用以下查询代码时抛出错误:
db.invoice.findAll({ where: { userId: 'ed8fdd40-b807-4e51-b1f5-90fb5b7f6e73' }, include: { all: true, nested: true } }).then(result => { console.log(result) })
错误堆栈:
c:\Users\brend\Desktop\projects\invoice-server\node_modules\sequelize\lib\model.js:1189 let associations = result.get(include.association.as); ^ TypeError: result.get is not a function at c:\Users\brend\Desktop\projects\invoice-server\node_modules\sequelize\lib\model.js:1189:37 at Array.reduce (<anonymous>) at c:\Users\brend\Desktop\projects\invoice-server\node_modules\sequelize\lib\model.js:1188:50 at Array.map (<anonymous>) at Model._findSeparate (c:\Users\brend\Desktop\projects\invoice-server\node_modules\sequelize\lib\model.js:1186:39) at invoice.findAll (c:\Users\brend\Desktop\projects\invoice-server\node_modules\sequelize\lib\model.js:1153:24) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) Node.js v20.10.0
成功但格式不符的查询代码
以下代码查询成功,但返回格式不符合预期(每个关联的invoiceItem对应一个独立的invoice对象):
db.invoice.findAll({ where: { userId: 'ed8fdd40-b807-4e51-b1f5-90fb5b7f6e73' }, include: "invoiceItems", raw : true , nest : true }).then(result => { console.log(result) })
模型配置代码
Invoice模型
module.exports = (sequelize, Sequelize, DataType) => { const Invoice = sequelize.define('invoice', { id: { type: DataType.UUID, primaryKey: true }, userId: { type: DataType.UUID, validate: { allowNull: false } }, name: { type: DataType.STRING(150) } //Additional fields left out here for simplicity },{ underscored: true }); Invoice.associate = models => { Invoice.hasMany(models.invoiceItem), { foreignKey: "invoiceId" } Invoice.belongsTo(models.user) }; return Invoice };
InvoiceItem模型
module.exports = (sequelize, Sequelize, DataType) => { const InvoiceItem = sequelize.define('invoiceItem', { id: { type: DataType.UUID, primaryKey: true }, invoiceId: { type: DataType.UUID, validate: { allowNull: false } }, userId: { type: DataType.UUID, validate: { allowNull: false } }, name: { type: DataType.STRING(150) } //Additional fields left out here for simplicity },{ underscored: true }); InvoiceItem.associate = models => { InvoiceItem.belongsTo(models.invoice, { foreignKey: "invoiceId" }) InvoiceItem.belongsTo(models.user), { foreignKey: "userId" }}; return InvoiceItem };
模型整合index.js
'use strict'; const fs = require('fs'); const path = require('path'); const Sequelize = require('sequelize'); const basename = path.basename(__filename); const sequelize = require('../config/database.js') const db = {} db.Sequelize = Sequelize; db.sequelize = sequelize; fs.readdirSync(__dirname) .filter(file => { return ( file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js' && file.indexOf('.test.js') === -1 ); }) .forEach(file => { const model = require(path.join(__dirname, file))(db.sequelize, db.Sequelize, db.Sequelize.DataTypes) db[model.name] = model; }); Object.keys(db).forEach(modelName => { if (db[modelName].associate) { db[modelName].associate(db); } }); module.exports = db;
问题排查及解决思路
核心问题:关联配置语法错误
模型关联配置中存在逗号位置错误,导致关联选项未被正确传入Sequelize,关联关系未正确建立:
- Invoice模型中,
Invoice.hasMany(models.invoiceItem)后面的逗号写在了括号外,导致{ foreignKey: "invoiceId" }被当作独立语句而非关联选项。 - InvoiceItem模型中,
InvoiceItem.belongsTo(models.user)同样存在逗号位置错误。
修正后的关联配置
修正Invoice模型的associate方法:
Invoice.associate = models => { Invoice.hasMany(models.invoiceItem, { foreignKey: "invoiceId" }); Invoice.belongsTo(models.user); };
修正InvoiceItem模型的associate方法:
InvoiceItem.associate = models => { InvoiceItem.belongsTo(models.invoice, { foreignKey: "invoiceId" }); InvoiceItem.belongsTo(models.user, { foreignKey: "userId" }); };
正确的查询代码
去掉raw: true(该配置会返回纯数据库查询结果,无法自动合并关联数据为嵌套数组),通过实例的get({ plain: true })方法转换为纯JS对象,即可得到期望的嵌套格式:
db.invoice.findAll({ where: { userId: 'ed8fdd40-b807-4e51-b1f5-90fb5b7f6e73' }, include: ['invoiceItems'] }).then(result => { // 将Sequelize实例转换为嵌套结构的纯JS对象 const formattedResult = result.map(invoice => invoice.get({ plain: true })); console.log(formattedResult); });
内容的提问来源于stack exchange,提问作者Brenden
相关产品推荐
相关产品推荐

