TypeORM多对多关联innerJoin后如何通过关联表ID筛选结果
解决TypeORM多对多关联同时匹配多个关联项的筛选问题
核心逻辑
要筛选同时包含所有指定服务ID的医生,不能直接用IN条件(IN只需匹配任意一个ID即可),需要通过「统计匹配的服务数量是否等于目标ID数组长度」的方式判定是否完全匹配,同时为了保留TypeORM实体映射能力,采用子查询+主查询分离的方式实现。
实现代码
const servicesArray = [1, 2]; // 子查询:筛选出同时包含所有指定服务的医生ID列表 const matchedDoctorIds = await this.doctorsRepository .createQueryBuilder('doctor') .innerJoin('doctor.services', 'services') .where('services.id IN (:...ids)', { ids: servicesArray }) .groupBy('doctor.id') // 若多对多中间表无重复关联记录,可去掉DISTINCT .having('COUNT(DISTINCT services.id) = :targetCount', { targetCount: servicesArray.length }) .select('doctor.id') .getRawMany(); // 提取医生ID数组,字段名根据你的命名策略可能为doctorId/doctor_id,自行调整即可 const doctorIds = matchedDoctorIds.map(item => item.doctor_id); // 主查询:查询符合条件的医生及关联服务 const result = await this.doctorsRepository .createQueryBuilder('doctor') .innerJoinAndSelect('doctor.services', 'services') .where('doctor.id IN (:...doctorIds)', { doctorIds }) // 如果需要返回的services仅包含筛选的指定服务,可添加下面这行,完全匹配你给出的预期结果 .andWhere('services.id IN (:...ids)', { ids: servicesArray }) .getMany();
原方案问题说明
- 直接使用
services.id IN (:...ids)条件:只要医生关联了任意一个目标服务就会被返回,无法满足「同时包含所有目标服务」的要求 - 直接在主查询添加统计字段和分组:
getMany()方法只会映射实体定义的属性,额外的统计字段不会被识别,无法得到规范的实体结构,仅适合配合getRawMany()使用
内容的提问来源于stack exchange,提问作者ShaSha
相关产品推荐
相关产品推荐

