使用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
相关产品推荐
相关产品推荐

