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

使用Op.in+offset/limit时Sequelize与MySQL查询结果条数不一致

问题解决:Sequelize查询与原生SQL结果不一致的调整方案

问题根源分析

对比你的Sequelize代码和原生SQL,存在以下关键差异导致结果条数不同:

  • Op.in参数错误包裹双层数组,匹配逻辑失效
  • 未对projectProposalResearchFields添加软删除(deleted_at IS NULL)过滤
  • 关联类型不匹配:原生用INNER JOIN,Sequelize默认对hasMany关联使用LEFT JOIN
  • 过滤字段层级与原生不一致,且status的条件位置不符合原生逻辑

修改后的Sequelize查询代码

const projectProposalList = await this.projectProposalRepository.findAll({
  attributes: [
    'id',
    'vietnameseName',
    'englishName',
    'implementationMonths',
    'totalExpenditure',
    'createdAt',
  ],
  include: [
    {
      model: ProjectProposalStatus,
      required: true, // 强制INNER JOIN,匹配原生SQL关联逻辑
      where: {
        name: ProjectProposalStatusEnum.REVISE // 将status条件移至关联ON子句,贴近原生
      }
    },
    {
      model: ProjectProposalResearchField,
      required: true, // 强制INNER JOIN,匹配原生SQL关联逻辑
      include: [ResearchField],
      where: {
        deletedAt: null, // 添加软删除过滤,对应原生的deleted_at IS NULL
        researchFieldsId: { // 直接过滤关联表字段,和原生逻辑完全一致
          [Op.in]: researchFieldIds // 移除多余的数组包裹
        }
      }
    },
    {
      model: ResearchType,
      // 默认是LEFT OUTER JOIN,和原生一致,无需额外设置
    },
  ],
  offset: Number(first),
  limit: projectProposalsPerPage,
  subQuery: false,
  order: [['createdAt', 'ASC']],
});

关键修改说明

  • 修正Op.in参数:移除researchFieldIds外层的数组包裹,确保IN条件能正确匹配多个ID
  • 添加软删除过滤:在ProjectProposalResearchField的关联条件中加入deletedAt: null,过滤已删除的关联记录
  • 统一关联类型:给ProjectProposalStatus和ProjectProposalResearchField的关联设置required: true,强制生成INNER JOIN,和原生SQL的关联逻辑对齐
  • 调整条件位置:将status的名称条件移至关联的where中,对应原生SQL的ON子句条件,避免主表where子句使用关联字段带来的查询差异
  • 对齐过滤字段:直接使用ProjectProposalResearchField的researchFieldsId字段过滤,和原生SQL中直接查询research_fields_id的逻辑完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 07:07:11