You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 20:45:39