TypeORM 中的 Postgres 枚举

Posted

技术标签:

【中文标题】TypeORM 中的 Postgres 枚举【英文标题】:Postgres enum in TypeORM 【发布时间】:2017-12-11 23:27:17 【问题描述】:

在 TypeORM 中,如何创建一个 postgres 枚举类型 Gender 就像在这个原始查询中一样

CREATE TYPE public.Gender AS ENUM (
    'male', 'female'
);
ALTER TABLE public.person ALTER COLUMN gender TYPE public.gender USING gender::gender;

并在 Entity 类中使​​用它?

我试过了

@Entity()
export class Person 
    @Column('enum')
    gender: 'male' | 'female'

但显然这不是正确的方法,因为我收到错误消息“类型 enum 不存在”。

我也不想使用 typescript 枚举,因为它会在数据库中给我一堆 0 和 1。

【问题讨论】:

【参考方案1】:

编辑:这个答案仍然有效,但有点过时,因为0.1.0 alpha 版本的 TypeORM 支持 PostgreSQL 和 mysql 的枚举。


PostgreSQL 有一个内置的枚举类型,但不幸的是TypeORM 目前是only supports it for MySQL。

但是,您可以通过将 @Column 类型用作 int 并将枚举用于您的字段类型,使用 int 类型枚举实现类似的结果。

enum Gender 
  Male,
  Female,
  Other


@Entity()
export class Person 
    @Column('int')
    gender: Gender

(此方法允许您在需要时使用@IsEnum decorator from class-validator 来验证输入)

您也可以使用字符串枚举(TypeScript 2.4 上可用,请查看 Typescript `enum` from JSON string 以获得旧版本),如果是这种情况,只需将数据类型更改为 string

enum Gender 
  Male = 'male',
  Female = 'female',
  Other = 'other'


@Entity()
export class Person 
    @Column('text')
    gender: Gender

【讨论】:

【参考方案2】:

正如接受的答案所述,它现在在 postgres 中得到支持,但仍然存在错误:Github issue,修复可能会在下一个 RC 中发布。同时,我在线程上看到了一个不错的解决方案,我什至喜欢它而不是实际功能完全正常工作:

fwiw 我一直在使用带有检查约束的字符串枚举。很多 比创建全新数据的实际 postgres 枚举更灵活 postgres 索引中的类型并且真的很难管理(更改表, 等等)

export function CheckEnum(tableName: string, fieldName: string, enumValue: any) 
  // Hash enum value and put it as part of constraint name so we can
  // force typeorm to generate migration for enum changes.
  const hash = crypto
    .createHash('sha1')
    .update(Object.values(enumValue).join(''))
    .digest('hex')
  return Check(
    // https://til.hashrocket.com/posts/8f87c65a0a-postgresqls-max-identifier-length-is-63-bytes
    `cke_$tableName_$fieldName_$hash`.slice(0, 63),
    `$fieldName in ($Object.values(enumValue).map(t => `'$t'`))`,
  )

然后像这样使用它

export enum Gender 
  Male = 'male',
  Female = 'female',
  Other = 'other'


@Entity()
@CheckEnum('person', 'gender', Gender)
export class Person 

【讨论】:

【参考方案3】:

对于 Postgres,列类型应该是“文本”,而不是“字符串”,因为字符串会导致 DataTypeNotSupportedError:“postgres”数据库不支持“”中的数据类型“string”。

【讨论】:

【参考方案4】:

TypeOrm 现在支持 Enum for postgres

docs

postgres 和 mysql 支持枚举列类型。有多种可能的列定义:

使用打字稿枚举:

export enum UserRole 
    ADMIN = "admin",
    EDITOR = "editor",
    GHOST = "ghost"


@Entity()
export class User 

    @PrimaryGeneratedColumn()
    id: number;

    @Column(
        type: "enum",
        enum: UserRole,
        default: UserRole.GHOST
    )
    role: UserRole;



使用带有枚举值的数组:

export type UserRoleType = "admin" | "editor" | "ghost",

@Entity()
export class User 

    @PrimaryGeneratedColumn()
    id: number;

    @Column(
        type: "enum",
        enum: ["admin", "editor", "ghost"],
        default: "ghost"
    )
    role: UserRoleType;

【讨论】:

【参考方案5】:

请参阅@noam steiner 的回答,但 TypeORM 会识别枚举类型而不明确提供它,所以这就足够了:

enum SomeEnum
  # ...


class Entity 
  @Field()
  @Column()
  someEnumField: SomeEnum;

【讨论】:

【参考方案6】:

值得一提的是,在多个实体中使用相同的枚举可能会导致奇怪的枚举缺失属性错误。我花了几个小时才弄清楚这个问题。

【讨论】:

以上是关于TypeORM 中的 Postgres 枚举的主要内容,如果未能解决你的问题,请参考以下文章

typeORM: "message": "\"postgres\" 数据库不支持 \"..." 中的数据类型 \"Obj

如何使用 Typeorm 创建与 Postgres 的连接

如何在 typeorm、postgres 中组合 3 列唯一的?

我如何将 Postgres DateRange 类型与 TypeOrm 一起使用

使用 TypeOrm 中的关系更新表

存储 GeoJson 点并在给定距离/半径内查找点 | NODEJS、Postgres、NestJs、TypeOrm