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

如何在TypeORM QueryBuilder中用getOne()获取JSONB列指定键值?

解决TypeORM QueryBuilder中getOne()获取JSONB指定键值的问题

要让getOne()正确映射JSONB字段的指定键值,核心是让查询结果的别名与实体中的属性一一对应——因为getOne()会自动将查询结果映射到实体类的属性上。以下是两种可行方案:

方案一:新增实体属性并指定查询别名

  1. 修改Workout实体:添加一个用于接收目标键值的属性,设置select: false避免默认查询该字段:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity('workouts')
export class Workout {
  @PrimaryGeneratedColumn('uuid')
  uuid: string;

  @Column('jsonb')
  name: Record<string, string>; // 原JSONB类型字段

  // 新增属性,用于存储name中'it'键对应的值
  @Column({ type: 'text', nullable: true, select: false })
  nameIt: string;
}
  1. 调整QueryBuilder代码:将JSONB提取的结果别名设为新增的实体属性名:
const workout = await this.workouts
  .createQueryBuilder('workout')
  .select(['workout.uuid', `workout.name ->> 'it'` as 'nameIt'])
  .where('workout.uuid = :workoutUuid', { workoutUuid })
  .getOne();

return workout; // 此时workout.nameIt会包含JSONB中'it'键的值

方案二:使用@AfterLoad钩子(加载后提取)

如果不想新增数据库映射属性,可以用实体的加载钩子在查询完成后从JSONB字段中提取值:

  1. 修改Workout实体:添加临时属性和加载钩子:
import { Entity, Column, PrimaryGeneratedColumn, AfterLoad } from 'typeorm';

@Entity('workouts')
export class Workout {
  @PrimaryGeneratedColumn('uuid')
  uuid: string;

  @Column('jsonb')
  name: Record<string, string>;

  // 临时属性,无需@Column注解
  nameIt?: string;

  @AfterLoad()
  loadItalianName() {
    // 从JSONB字段中提取'it'键的值
    this.nameIt = this.name?.['it'];
  }
}
  1. 调整QueryBuilder代码:只需查询原有的JSONB字段即可,钩子会自动处理:
const workout = await this.workouts
  .createQueryBuilder('workout')
  .select(['workout.uuid', 'workout.name'])
  .where('workout.uuid = :workoutUuid', { workoutUuid })
  .getOne();

return workout; // workout.nameIt会自动加载'it'键的值

注意:方案一直接在数据库查询时提取值,性能更优;方案二更适合需要从JSONB中提取多个键值的场景,但会先加载整个JSONB字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 02:50:12