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

Typeorm getMany()未返回左连非关联实体问题排查

TypeORM getMany() 未返回非关联实体数据的问题解决

我在使用TypeORM的getMany()时遇到问题,执行以下代码仅返回Results实体,没有包含UserAnag的数据:

const res = await this.repo
  .createQueryBuilder('result')
  .leftJoinAndSelect(
    UserAnag,
    'useranag',
    'useranag.playerId = result.playerId',
  )
  .where('result.server = :idServer', { idServer: serverId })
  .andWhere('result.raceId = :idRace', { idRace: raceId })
  .getMany();

改用getRawMany()可以拿到所有数据,但返回的是原始扁平化结构:

result.id,
result.position,
useranag.id,
useranag.name

我期望getMany()返回嵌套结构:

result.id,
result.position,
useranag: {
   id: xx,
   name: yyy
}

UserAnag和Results通过playerId关联,但实体中没有定义正式的关联关系。TypeORM文档提到可以对非关联实体使用leftJoinAndSelect配合getMany(),但实际没达到预期效果。

实体定义如下:
Results 实体

@Entity()
export class Results {
@PrimaryGeneratedColumn()
id: number;
@Column()
position: number;
@Column()
laps: number;
@Column({ type: 'time', precision: 3 })
bestLaps: Date;
@Column({ type: 'time', precision: 3 })
gap: Date;
@Column()
penalties: number;
@Column()
server: number;
@Column()
playerId: string;

@ManyToOne(() => Cars, (cars) => cars.result)
car: Cars;
@ManyToOne(
() => Competitionraces,
(competitionRaces) => competitionRaces.result,
)
race: Competitionraces;
}

UserAnag 实体

@Entity()
export class UserAnag {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
surname: string;
@Column()
psn: string;
@Column()
discord: string;
@Column()
drivernumber: number;
@Column()
playerId: number;

@OneToOne(() => User, (user) => user.useranag, {
onDelete: 'CASCADE',
})
@JoinColumn()
user: User;

@ManyToOne(() => Discord, (useranag) => useranag.siglaTeam)
discordTeam: Discord;
}

问题本质

getMany()的工作逻辑依赖实体的元数据,它只会将查询结果填充到实体类已定义的属性中。你的Results实体里没有useranag属性,即使leftJoinAndSelect查询到了UserAnag的数据,getMany()也无法识别该把数据挂载到哪里,因此只会返回Results本身的字段。而getRawMany()是直接返回数据库的原始查询行,所以能看到所有关联字段。

解决方案

方案1:在实体中定义正式关联(推荐)

既然两个实体通过playerId关联,直接在Results中添加关联映射,让TypeORM自动处理数据嵌套:

  1. 修改Results实体,添加UserAnag的关联(注意统一playerId的类型:当前Results的playerId是string,UserAnag的是number,需要先统一类型,比如都改成string或number):
@Entity()
export class Results {
  // 保留原有所有字段...

  @Column()
  playerId: string; // 确保和UserAnag的playerId类型一致

  // 添加关联映射,手动指定关联字段(因为不是默认的外键名)
  @ManyToOne(() => UserAnag)
  @JoinColumn({ name: 'playerId', referencedColumnName: 'playerId' })
  useranag: UserAnag;
}
  1. (可选)如果需要反向关联,在UserAnag中添加:
@Entity()
export class UserAnag {
  // 保留原有所有字段...

  @OneToMany(() => Results, result => result.useranag)
  results: Results[];
}

修改后,原来的getMany()代码就能直接返回包含useranag嵌套对象的Results实体了。

方案2:手动转换原始数据(不修改实体)

如果不想修改实体结构,可以用getRawMany()获取数据后手动映射成期望的嵌套结构:

const res = await this.repo
  .createQueryBuilder('result')
  .leftJoin(
    UserAnag,
    'useranag',
    'useranag.playerId = result.playerId',
  )
  .select([
    'result.id AS result_id',
    'result.position AS result_position',
    'useranag.id AS useranag_id',
    'useranag.name AS useranag_name',
  ])
  .where('result.server = :idServer', { idServer: serverId })
  .andWhere('result.raceId = :idRace', { idRace: raceId })
  .getRawMany()
  .then(rawList => rawList.map(item => ({
    id: item.result_id,
    position: item.result_position,
    useranag: {
      id: item.useranag_id,
      name: item.useranag_name
      // 按需添加其他UserAnag字段
    }
  })));

或者使用QueryBuilder的setTransformer来处理转换:

const res = await this.repo
  .createQueryBuilder('result')
  .leftJoinAndSelect(
    UserAnag,
    'useranag',
    'useranag.playerId = result.playerId',
  )
  .where('result.server = :idServer', { idServer: serverId })
  .andWhere('result.raceId = :idRace', { idRace: raceId })
  .setTransformer(rawItem => {
    // 提取useranag字段并嵌套
    const transformed = {
      id: rawItem.result_id,
      position: rawItem.result_position,
      // 保留Results的其他字段...
      useranag: {
        id: rawItem.useranag_id,
        name: rawItem.useranag_name
      }
    };
    // 删除扁平化的前缀字段(可选)
    Object.keys(rawItem).forEach(key => {
      if (key.startsWith('useranag_')) delete transformed[key];
    });
    return transformed;
  })
  .getRawMany();

内容的提问来源于stack exchange,提问作者Massimiliano Oreto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:48:09