Sequelize如何仅返回嵌套关联子模型存在匹配记录的主表数据
解决方案
下面提供两种可直接落地的实现方式,可根据项目实际场景选择:
方式一:拆分关联逻辑,分离过滤和数据拉取逻辑
该方法完全基于Sequelize原生关联语法实现,无需编写原生SQL:
你之前直接在子关联上加where过滤只裁剪子级数据、不过滤主表的核心原因是默认关联采用左连接(LEFT JOIN),只要主表匹配外层条件就会返回。我们可以新增一个仅用于过滤的关联配置,设置为内连接模式过滤主表,再保留原有全量关联拉取完整嵌套数据即可。
示例代码如下:
const targetUserId = 你传入的待匹配用户ID参数; const results = await WorkflowAssignation.findAndCountAll({ limit: limit, offset: offset, where: { userId: userIds, status: status }, include: [ // 仅用于过滤的关联配置,不会返回额外字段 { model: WorkflowStepAssignation, as: "steps", // 必须和你定义关联时的别名保持一致,和下面order里的配置对应 attributes: [], // 不返回该表任何字段,避免污染返回结构 required: true, // 开启内连接,无匹配关联数据时主表记录直接被过滤 include: [{ model: WorkflowStepAssignationHasUser, attributes: [], required: true, where: { userId: targetUserId // 这里加用户ID过滤条件 } }] }, // 原有全量关联配置,不要加任何过滤条件,用于返回完整嵌套数据 { model: WorkflowStepAssignation, as: "steps", include: [ { model: WorkflowStepAssignationHasUser, include: [ users ]} ] }, { model: users } ], distinct: true, order: [ [ 'createdAt', 'DESC'], [ { model: WorkflowStepAssignation, as: "steps" }, 'stepNumber', 'ASC' ] ] });
方式二:使用EXISTS子查询(数据量较大时更推荐)
该方法直接在主表过滤逻辑里加原生EXISTS子查询,性能优于第一种方式,无需额外关联两次表。
示例代码如下:
const targetUserId = 你传入的待匹配用户ID参数; const { Op } = require('sequelize'); // 提前引入Sequelize操作符 const results = await WorkflowAssignation.findAndCountAll({ limit: limit, offset: offset, where: { userId: userIds, status: status, [Op.and]: [ // 注意替换下方SQL里的表名、字段名为你数据库中实际的命名 Sequelize.literal(` EXISTS ( SELECT 1 FROM workflow_step_assignation wsa INNER JOIN workflow_step_assignation_has_user wsahu ON wsa.id = wsahu.workflow_step_assignation_id WHERE wsa.workflow_assignation_id = WorkflowAssignation.id AND wsahu.userId = ${targetUserId} ) `) ] }, include: [ { model: WorkflowStepAssignation, include: [ { model: WorkflowStepAssignationHasUser, include: [ users ]} ] }, { model: users } ], distinct: true, order: [ [ 'createdAt', 'DESC'], [ { model: WorkflowStepAssignation, as: "steps" }, 'stepNumber', 'ASC' ] ] });
注意事项
如果你的关联定义时没有设置别名as: "steps",需要删除代码中对应的as配置,保持和你实际的关联定义一致即可。
内容的提问来源于stack exchange,提问作者Jose Raul Perera
相关产品推荐
相关产品推荐

