TypeORM 中的 Postgres 枚举
Postgres enum in TypeORM
在 TypeORM 中,如何创建一个 postgres 枚举类型 Gender,就像在这个原始查询中一样
CREATE TYPE public.Gender AS ENUM (
'male', 'female'
);
ALTER TABLE public.person ALTER COLUMN gender TYPE public.gender USING gender::gender;
并在实体中使用它 class?
我试过了
@Entity()
export class Person {
@Column('enum')
gender: 'male' | 'female'
}
但显然这不是正确的方法,因为我收到错误消息“type enum does not exist”。
我也不想使用 typescript 枚举,因为它会在数据库中给我一堆 0 和 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 上可用,请检查 了解旧版本),如果是这种情况,只需将数据类型更改为 string
。
enum Gender {
Male = 'male',
Female = 'female',
Other = 'other'
}
@Entity()
export class Person {
@Column('text')
gender: Gender
}
正如已接受的答案所述,它现在在 postgres 中受支持,但仍然存在问题:Github issue,修复可能会在下一个 RC 中发布。同时,我在线程上看到了一个很好的解决方案,我什至更喜欢它而不是实际功能完全正常工作:
fwiw I've been using string enum with check constraint. It's a lot
more flexible than actual postgres enum, which creates whole new data
types in postgres index and are really hard to manage (alter table,
etc.)
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}'`)})`,
)
}
And use it like so
export enum Gender {
Male = 'male',
Female = 'female',
Other = 'other'
}
@Entity()
@CheckEnum('person', 'gender', Gender)
export class Person {
对于 Postgres,列类型应为 'text',而不是 'string',因为字符串结果为
DataTypeNotSupportedError:"postgres" 数据库不支持“”中的数据类型 "string"。
Postgres 的 TypeOrm 现在支持枚举
由 docs
enum column type is supported by postgres and mysql. There are various possible column definitions:
Using typescript enums:
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;
}
Using array with enum values:
export type UserRoleType = "admin" | "editor" | "ghost",
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({
type: "enum",
enum: ["admin", "editor", "ghost"],
default: "ghost"
})
role: UserRoleType;
}
请参阅@noam steiner 的回答,但 TypeORM 将识别枚举类型而不显式提供它,所以这就足够了:
enum SomeEnum{
# ...
}
class Entity {
@Field()
@Column()
someEnumField: SomeEnum;
}
值得一提的是,在多个实体中使用相同的枚举可能会导致奇怪的枚举属性缺失错误。我花了几个小时才弄清楚这个问题。
在 TypeORM 中,如何创建一个 postgres 枚举类型 Gender,就像在这个原始查询中一样
CREATE TYPE public.Gender AS ENUM (
'male', 'female'
);
ALTER TABLE public.person ALTER COLUMN gender TYPE public.gender USING gender::gender;
并在实体中使用它 class?
我试过了
@Entity()
export class Person {
@Column('enum')
gender: 'male' | 'female'
}
但显然这不是正确的方法,因为我收到错误消息“type enum does not exist”。
我也不想使用 typescript 枚举,因为它会在数据库中给我一堆 0 和 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 上可用,请检查 string
。
enum Gender {
Male = 'male',
Female = 'female',
Other = 'other'
}
@Entity()
export class Person {
@Column('text')
gender: Gender
}
正如已接受的答案所述,它现在在 postgres 中受支持,但仍然存在问题:Github issue,修复可能会在下一个 RC 中发布。同时,我在线程上看到了一个很好的解决方案,我什至更喜欢它而不是实际功能完全正常工作:
fwiw I've been using string enum with check constraint. It's a lot more flexible than actual postgres enum, which creates whole new data types in postgres index and are really hard to manage (alter table, etc.)
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}'`)})`,
)
}
And use it like so
export enum Gender {
Male = 'male',
Female = 'female',
Other = 'other'
}
@Entity()
@CheckEnum('person', 'gender', Gender)
export class Person {
对于 Postgres,列类型应为 'text',而不是 'string',因为字符串结果为 DataTypeNotSupportedError:"postgres" 数据库不支持“”中的数据类型 "string"。
Postgres 的 TypeOrm 现在支持枚举
由 docs
enum column type is supported by postgres and mysql. There are various possible column definitions:
Using typescript enums:
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;
}
Using array with enum values:
export type UserRoleType = "admin" | "editor" | "ghost",
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({
type: "enum",
enum: ["admin", "editor", "ghost"],
default: "ghost"
})
role: UserRoleType;
}
请参阅@noam steiner 的回答,但 TypeORM 将识别枚举类型而不显式提供它,所以这就足够了:
enum SomeEnum{
# ...
}
class Entity {
@Field()
@Column()
someEnumField: SomeEnum;
}
值得一提的是,在多个实体中使用相同的枚举可能会导致奇怪的枚举属性缺失错误。我花了几个小时才弄清楚这个问题。