Typeorm查询问题:获取含指定用户的Bill并返回完整friends数组
问题描述
模型定义:
@Entity('bill') export class Bill { @Column() title: string; @Column({ nullable: true }) description?: string; @ManyToMany(() => User, { nullable: true }) @JoinTable() friends?: User[]; }
需要获取所有friends数组包含指定用户的Bill数据行,尝试了以下查询:
const bills = await this.billRepo.find({ where: { friends: { id: user.id, }, }, relations: ['friends'] });
该查询能正确筛选出目标数据行,但返回的friends数组仅包含用于查询的指定用户,而非完整的friends数组。
解决方案
这是TypeORM使用find方法查询多对多关系时的常见问题:直接在where中指定关联实体条件会触发内连接并过滤关联结果,导致返回的关联数组只保留匹配的条目。
要保留完整的friends数组,需用QueryBuilder分离筛选条件与关联数据加载逻辑:
方法一:使用左连接筛选
const bills = await this.billRepo .createQueryBuilder('bill') .leftJoinAndSelect('bill.friends', 'friend') // 加载完整的friends关联数据 .where('friend.id = :userId', { userId: user.id }) // 筛选包含指定用户的Bill .getMany();
方法二:使用Exists子查询(避免笛卡尔积重复)
如果多对多关联数据较多,会产生笛卡尔积导致重复结果,可改用子查询筛选:
const bills = await this.billRepo .createQueryBuilder('bill') .leftJoinAndSelect('bill.friends', 'friend') .whereExists(qb => qb .select('1') .from('bill_friends', 'bf') // 替换为实际的多对多中间表名,默认规则为[实体名1]_[实体名2] .where('bf.billId = bill.id') .andWhere('bf.friendId = :userId', { userId: user.id }) ) .getMany();
注意:中间表名称需根据项目实际生成的表名调整,若自定义了中间表,要替换为对应名称。
内容的提问来源于stack exchange,提问作者Saurabh
相关产品推荐
相关产品推荐

