TypeORM左连接条件问题:保留完整审批人同时筛选指定审批请求
解决TypeORM筛选请求时保留完整审批人列表的问题
方法一:子查询获取目标请求ID后加载完整数据
先筛选出包含EMP002作为审批人的请求ID,再基于这些ID查询请求并加载所有审批人:
// 第一步:获取符合条件的请求ID集合 const targetRequestIds = await this.requestRepository .createQueryBuilder('request') .innerJoin('request.approvers', 'approvers') .where('approvers.employeeCode = :code', { code: 'EMP002' }) .select('request.id') .getRawMany() .then(rows => rows.map(row => row.request_id)); // 第二步:查询目标请求并加载完整审批人列表 const requests = await this.requestRepository .createQueryBuilder('request') .leftJoinAndMapMany( 'request.approvers', RequestApprover, 'approvers', 'request.id = approvers.requestId' ) .where('request.id IN (:...ids)', { ids: targetRequestIds }) .getMany();
方法二:使用EXISTS子句筛选请求,同时加载关联数据
通过EXISTS子句判断请求是否存在指定审批人,主查询保留所有关联的审批人数据:
const requests = await this.requestRepository .createQueryBuilder('request') .leftJoinAndMapMany( 'request.approvers', RequestApprover, 'approvers', 'request.id = approvers.requestId' ) .where(qb => { const subQuery = qb.subQuery() .select('1') .from(RequestApprover, 'ra') .where('ra.requestId = request.id') .andWhere('ra.employeeCode = :code', { code: 'EMP002' }) .getQuery(); return `EXISTS(${subQuery})`; }) .setParameter('code', 'EMP002') .getMany();
方法三:结合关系装饰器与EXISTS条件查询
如果你的Request实体已经通过@OneToMany装饰器关联了RequestApprover,可以直接用find方法结合子查询:
const requests = await this.requestRepository.find({ relations: ['approvers'], where: (qb) => { qb.whereExists(qb.subQuery() .select('1') .from(RequestApprover, 'ra') .where('ra.requestId = request.id') .andWhere('ra.employeeCode = :code', { code: 'EMP002' }) ); }, parameters: { code: 'EMP002' } });
原写法丢失数据的原因
你之前直接在leftJoinAndMapMany后添加andWhere('approvers.employeeCode = 'EMP002'),这个条件会过滤掉所有关联审批人不符合的行,最终返回的request.approvers只会保留匹配EMP002的条目——本质是把筛选条件作用在了关联数据行上,而非请求本身。上面的方法都是先筛选出「包含指定审批人的请求」,再为这些请求加载所有审批人数据,从而同时满足筛选需求和完整数据的要求。
内容的提问来源于stack exchange,提问作者Đoàn Đức Bảo
相关产品推荐
相关产品推荐

