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

如何移除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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:20:40