跳至主要内容

自定义模型和字段名称

Prisma 客户端 API 是根据您在 Prisma 架构 中的模型生成的。模型通常是您数据库表的 1:1 映射。

在某些情况下,尤其是在使用 内省 时,将数据库表和列的命名与您在 Prisma 客户端 API 中使用的名称分离可能很有用。这可以通过您在 Prisma 架构中的 @map@@map 属性来实现。

您可以使用 @map@@map 分别重命名 MongoDB 字段和集合。本页使用关系型数据库示例。

示例:关系型数据库

假设您有一个类似于此的 PostgreSQL 关系型数据库架构

CREATE TABLE users (
user_id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(256),
email VARCHAR(256) UNIQUE NOT NULL
);
CREATE TABLE posts (
post_id SERIAL PRIMARY KEY NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
title VARCHAR(256) NOT NULL,
content TEXT,
author_id INTEGER REFERENCES users(user_id)
);
CREATE TABLE profiles (
profile_id SERIAL PRIMARY KEY NOT NULL,
bio TEXT,
user_id INTEGER NOT NULL UNIQUE REFERENCES users(user_id)
);
CREATE TABLE categories (
category_id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(256)
);
CREATE TABLE post_in_categories (
post_id INTEGER NOT NULL REFERENCES posts(post_id),
category_id INTEGER NOT NULL REFERENCES categories(category_id)
);
CREATE UNIQUE INDEX post_id_category_id_unique ON post_in_categories(post_id int4_ops,category_id int4_ops);

当您使用该架构内省数据库时,您将获得一个类似于此的 Prisma 架构

model categories {
category_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
post_in_categories post_in_categories[]
}

model post_in_categories {
post_id Int
category_id Int
categories categories @relation(fields: [category_id], references: [category_id], onDelete: NoAction, onUpdate: NoAction)
posts posts @relation(fields: [post_id], references: [post_id], onDelete: NoAction, onUpdate: NoAction)

@@unique([post_id, category_id], map: "post_id_category_id_unique")
}

model posts {
post_id Int @id @default(autoincrement())
created_at DateTime? @default(now()) @db.Timestamptz(6)
title String @db.VarChar(256)
content String?
author_id Int?
users users? @relation(fields: [author_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
post_in_categories post_in_categories[]
}

model profiles {
profile_id Int @id @default(autoincrement())
bio String?
user_id Int @unique
users users @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
}

model users {
user_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts posts[]
profiles profiles?
}

当生成 Prisma 客户端 API 时,此 Prisma 架构存在一些“问题”。

遵守 Prisma ORM 的命名约定

Prisma ORM 具有 命名约定,即使用 **驼峰命名法** 并使用 **单数形式** 来命名 Prisma 模型。如果不满足这些命名约定,Prisma 架构会变得难以理解,生成的 Prisma 客户端 API 也会显得不太自然。请考虑以下生成的模型

model users {
user_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts posts[]
profiles profiles?
}

虽然 profiles 指的是 1:1 关系,但其类型目前被称为 profiles(复数形式),这暗示这种关系中可能存在多个 profiles。使用 Prisma ORM 约定,模型和字段理想情况下应该命名如下

model User {
user_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts Post[]
profile Profile?
}

由于这些字段是“Prisma ORM 级别的” 关系字段,它们不会显示出来,因此您可以在 Prisma 架构中手动重命名它们。

标注关系字段的命名

外键以 标注关系字段 及其在 Prisma 架构中的相应关系标量字段的组合形式表示。以下是 SQL 架构中所有关系的当前表示方式

model categories {
category_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
post_in_categories post_in_categories[] // virtual relation field
}

model post_in_categories {
post_id Int // relation scalar field
category_id Int // relation scalar field
categories categories @relation(fields: [category_id], references: [category_id], onDelete: NoAction, onUpdate: NoAction) // virtual relation field
posts posts @relation(fields: [post_id], references: [post_id], onDelete: NoAction, onUpdate: NoAction)

@@unique([post_id, category_id], map: "post_id_category_id_unique")
}

model posts {
post_id Int @id @default(autoincrement())
created_at DateTime? @default(now()) @db.Timestamptz(6)
title String @db.VarChar(256)
content String?
author_id Int?
users users? @relation(fields: [author_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
post_in_categories post_in_categories[]
}

model profiles {
profile_id Int @id @default(autoincrement())
bio String?
user_id Int @unique
users users @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
}

model users {
user_id Int @id @default(autoincrement())
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts posts[]
profiles profiles?
}

使用 @map@@map 重命名 Prisma 客户端 API 中的字段和模型

您可以通过使用 @map@@map 属性将 Prisma 客户端中使用的字段和模型映射到数据库中的“原始”名称来“重命名”它们。对于上面的示例,您可以例如按如下方式标注您的模型。

在您使用 prisma db pull 内省数据库,您可以手动调整生成的 Prisma 架构,如下所示

model Category {
id Int @id @default(autoincrement()) @map("category_id")
name String? @db.VarChar(256)
post_in_categories PostInCategories[]

@@map("categories")
}

model PostInCategories {
post_id Int
category_id Int
categories Category @relation(fields: [category_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
posts Post @relation(fields: [post_id], references: [id], onDelete: NoAction, onUpdate: NoAction)

@@unique([post_id, category_id], map: "post_id_category_id_unique")
@@map("post_in_categories")
}

model Post {
id Int @id @default(autoincrement()) @map("post_id")
created_at DateTime? @default(now()) @db.Timestamptz(6)
title String @db.VarChar(256)
content String?
author_id Int?
users User? @relation(fields: [author_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
post_in_categories PostInCategories[]

@@map("posts")
}

model Profile {
id Int @id @default(autoincrement()) @map("profile_id")
bio String?
user_id Int @unique
users User @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)

@@map("profiles")
}

model User {
id Int @id @default(autoincrement()) @map("user_id")
name String? @db.VarChar(256)
email String @unique @db.VarChar(256)
posts Post[]
profiles Profile?

@@map("users")
}

通过这些更改,您现在遵守了 Prisma ORM 的命名约定,生成的 Prisma 客户端 API 感觉更“自然”。

// Nested writes
const profile = await prisma.profile.create({
data: {
bio: 'Hello World',
users: {
create: {
name: 'Alice',
email: '[email protected]',
},
},
},
})

// Fluent API
const userByProfile = await prisma.profile
.findUnique({
where: { id: 1 },
})
.users()
信息

prisma db pull 会在您重新内省数据库时保留您通过 @map@@map 在 Prisma 架构中定义的自定义名称。

重命名关系字段

Prisma ORM 级别的 关系字段(有时称为“虚拟关系字段”)仅存在于 Prisma 架构中,但实际上并未在底层数据库中体现出来。因此,您可以随意命名这些字段。

请考虑以下 SQL 数据库中不明确关系的示例

CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"author" integer NOT NULL,
"favoritedBy" INTEGER,
FOREIGN KEY ("author") REFERENCES "User"(id),
FOREIGN KEY ("favoritedBy") REFERENCES "User"(id)
);

Prisma ORM 的内省将输出以下 Prisma 架构

model Post {
id Int @id @default(autoincrement())
author Int
favoritedBy Int?
User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id], onDelete: NoAction, onUpdate: NoAction)
User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model User {
id Int @id @default(autoincrement())
Post_Post_authorToUser Post[] @relation("Post_authorToUser")
Post_Post_favoritedByToUser Post[] @relation("Post_favoritedByToUser")
}

由于虚拟关系字段 Post_Post_authorToUserPost_Post_favoritedByToUser 的名称基于生成的关联名称,因此它们在 Prisma 客户端 API 中看起来不太友好。在这种情况下,您可以重命名关系字段。例如

model Post {
id Int @id @default(autoincrement())
author Int
favoritedBy Int?
User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id], onDelete: NoAction, onUpdate: NoAction)
User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model User {
id Int @id @default(autoincrement())
writtenPosts Post[] @relation("Post_authorToUser")
favoritedPosts Post[] @relation("Post_favoritedByToUser")
}
信息

prisma db pull 会在您重新内省数据库时保留您在 Prisma 架构中定义的自定义关系字段。