如何移除Sequelize关联查询中自动添加的hutangs.id字段
解决Sequelize左连接自动生成未指定主键字段的问题
原始需求SQL
SELECT [pelanggan].[id], [pelanggan].[nama_pelanggan], [pelanggan].[hp], Format(ABS(SUM([hutangs].[nominal])), N'c', N'id-ID') AS [total], [hutangs].[id_pelanggan] AS [hutangs.id_pelanggan] FROM [pelanggan] AS [pelanggan] LEFT OUTER JOIN [hutang] AS [hutangs] ON [pelanggan].[id] = [hutangs].[id_pelanggan] WHERE [pelanggan].[kode_reseller] = N'MP0000001' GROUP BY [pelanggan].[id], [pelanggan].[nama_pelanggan], [pelanggan].[hp], [hutangs].[id_pelanggan] ORDER BY [pelanggan].[id] OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY;
用户编写的Sequelize代码(存在自动生成字段问题)
Pelanggan.findAndCountAll({ attributes: [ 'pelanggan.id', 'nama_pelanggan', 'hp', [db.sequelize.fn('Format', db.sequelize.fn('ABS', db.sequelize.fn('SUM', db.sequelize.col('hutangs.nominal'))), 'c', 'id-ID'), 'total'], ], include: [ { model : db.hutang, required: false, attributes: [ 'id_pelanggan', ], } ], where: { kode_reseller: "MP0000001" }, group: ['pelanggan.id','pelanggan.nama_pelanggan','pelanggan.hp','hutangs.id_pelanggan'], subQuery : false, limit: 5, offset: 0, }) .then(data => { res.send(data); }) .catch(err => { console.log(err) res.status(500).send({ message: err.message || "Some error occurred while retrieving tutorials." }); });
问题描述
执行上述代码时,Sequelize自动在SELECT语句中加入了未指定的[hutangs].[id] AS [hutangs.id]字段,导致查询出错。
解决方案
方法1:显式排除关联模型的主键字段
Sequelize默认会自动包含关联模型的主键(这里是hutang的id),即使未在attributes中指定。可以通过exclude选项显式排除该字段:
Pelanggan.findAndCountAll({ attributes: [ 'id', 'nama_pelanggan', 'hp', [db.sequelize.fn('Format', db.sequelize.fn('ABS', db.sequelize.fn('SUM', db.sequelize.col('hutangs.nominal'))), 'c', 'id-ID'), 'total'], ], include: [ { model : db.hutang, required: false, attributes: { include: ['id_pelanggan'], exclude: ['id'] // 显式排除hutang的id字段 }, } ], where: { kode_reseller: "MP0000001" }, group: ['Pelanggan.id','Pelanggan.nama_pelanggan','Pelanggan.hp','hutangs.id_pelanggan'], subQuery : false, limit: 5, offset: 0, })
方法2:不使用include,直接构建匹配原始SQL的查询
因为需求核心是聚合关联表数据,不需要返回嵌套的hutang对象,完全可以去掉include的嵌套返回逻辑,直接通过字段关联构建查询,避免自动生成多余字段:
Pelanggan.findAndCountAll({ attributes: [ 'id', 'nama_pelanggan', 'hp', [db.sequelize.fn('Format', db.sequelize.fn('ABS', db.sequelize.fn('SUM', db.sequelize.col('hutangs.nominal'))), 'c', 'id-ID'), 'total'], [db.sequelize.col('hutangs.id_pelanggan'), 'hutangs.id_pelanggan'] // 直接指定需要的关联字段 ], where: { kode_reseller: "MP0000001" }, // 手动指定左连接,不返回嵌套关联对象 include: [{ model: db.hutang, as: 'hutangs', required: false, attributes: [] // 空数组表示不返回任何hutang的嵌套字段 }], group: ['Pelanggan.id','Pelanggan.nama_pelanggan','Pelanggan.hp','hutangs.id_pelanggan'], subQuery : false, limit: 5, offset: 0, })
说明
方法2更推荐,完全匹配原始SQL的结构,既满足聚合需求,又避免了Sequelize自动添加多余字段的问题。
内容的提问来源于stack exchange,提问作者Sutrasno Andre Wibowo
相关产品推荐
相关产品推荐

