跳到主要内容

视图

警告

目前,对视图的支持还处于非常早期的预览功能阶段。您可以使用 view 关键字将视图添加到您的 Prisma 模式中,或者使用 db pull 内省数据库模式中的视图。除非使用 --create-only 标志手动将更改添加到您的迁移文件中,否则您还不能使用 Prisma Migrate 和 db push 将模式中的视图应用到您的数据库中。

有关此功能进度的更新,请关注 我们的 GitHub issue

数据库视图允许您命名和存储查询。在关系数据库中,视图是存储的 SQL 查询,可能包含多个表中的列,或计算值(如聚合)。在 MongoDB 中,视图是可查询的对象,其内容由其他集合上的聚合管道定义。

views 预览功能允许您使用 view 关键字在 Prisma 模式中表示视图。要在 Prisma ORM 中使用视图,请按照以下步骤操作

启用 views 预览功能

目前,对视图的支持还处于早期预览阶段。要启用 views 预览功能,请将 views 功能标志添加到 Prisma Schema 中 generator 块的 previewFeatures 字段中

schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["views"]
}

请在我们的专门 views 预览功能反馈 issue 中留下关于此预览功能的反馈。

在底层数据库中创建视图

目前,您无法使用 Prisma Migrate 和 db push 将在 Prisma 模式中定义的视图应用到数据库中。相反,您必须首先在底层数据库中创建视图,可以手动创建,也可以作为迁移的一部分创建。

例如,以下 Prisma 模式具有 User 模型和相关的 Profile 模型

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
profile Profile?
}

model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}

接下来,在底层数据库中创建一个 UserInfo 视图,该视图组合了 User 模型的 emailname 字段以及 Profile 模型的 bio 字段。

对于关系数据库,创建此视图的 SQL 语句是

CREATE VIEW "UserInfo" AS
SELECT u.id, email, name, bio
FROM "User" u
LEFT JOIN "Profile" p ON u.id = p."userId";

对于 MongoDB,您可以使用以下命令创建视图

db.createView('UserInfo', 'User', [
{
$lookup: {
from: 'Profile',
localField: '_id',
foreignField: 'userId',
as: 'ProfileData',
},
},
{
$project: {
_id: 1,
email: 1,
name: 1,
bio: '$ProfileData.bio',
},
},
{ $unwind: '$bio' },
])

将视图与 Prisma Migrate 和 db push 一起使用

如果您使用 Prisma Migrate 或 db push 将更改应用到您的 Prisma 模式,Prisma ORM 不会创建或运行任何与视图相关的 SQL。

要在迁移中包含视图,请运行 migrate dev --create-only,然后手动将视图的 SQL 添加到您的迁移文件中。或者,您可以手动在数据库中创建视图。

将视图添加到您的 Prisma 模式

要将视图添加到您的 Prisma 模式,请使用 view 关键字。

您可以按如下方式在您的 Prisma 模式中表示上面示例中的 UserInfo 视图

view UserInfo {
id Int @unique
email String
name String
bio String
}

手动编写

一个 view 块由两个主要部分组成

  • view 块定义
  • 视图的字段定义

这两个部分允许您在生成的 Prisma Client 中定义视图的名称,以及视图查询结果中存在的列。

定义 view

要定义上面示例中的 UserInfo 视图,首先使用 view 关键字在您的模式中定义一个名为 UserInfoview

view UserInfo {
// Fields
}

定义字段

视图的属性称为字段,它由以下部分组成

  • 字段名称
  • 字段类型

UserInfo 示例视图的字段可以定义如下

view UserInfo {
id Int @unique
email String
name String
bio String
}

view 块的每个字段都表示底层数据库中视图查询结果中的一列。

使用内省

警告

目前仅适用于 PostgreSQL、MySQL、SQL Server 和 CockroachDB。

如果您在数据库中定义了一个或多个现有视图,内省 将自动在您的 Prisma 模式中生成 view 块,以表示这些视图。

假设示例 UserInfo 视图存在于您的底层数据库中,运行以下命令将在您的 Prisma 模式中生成一个表示该视图的 view

npx prisma db pull

生成的 view 块将定义如下

/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
view UserInfo {
id Int?
email String?
name String?
bio String?

@@ignore
}

view 块最初是使用 @@ignore 属性生成的,因为 没有定义唯一标识符(这目前是视图预览功能的一个限制)。

警告

请注意,目前,当使用 PostgreSQL、MySQL、SQL Server 或 CockroachDB 时,db pull 仅内省模式中的视图。对该工作流程的支持将扩展到其他数据库提供商。

向内省的视图添加唯一标识符

为了能够在 Prisma Client 中使用内省的视图,您需要选择一个或多个字段定义为唯一标识符。

在上面的视图示例中,id 列引用了底层 User 表中唯一可标识的字段,因此该字段也可以用作 view 块中唯一可标识的字段。

为了使此 view 块有效,您需要

  • id 字段中删除可选标志 ?
  • @unique 属性添加到 id 字段
  • 删除 @@ignore 属性
  • 删除有关无效视图的生成的注释警告
/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
view UserInfo {
id Int?
id Int @unique
email String?
name String?
bio String?

@@ignore
}

当重新内省您的数据库时,对您的视图定义的任何自定义更改都将保留。

views 目录

内省具有一个或多个现有视图的数据库还将在您的 prisma 目录中创建一个新的 views 目录(从 Prisma 版本 4.12.0 开始)。此目录将包含一个以您的数据库模式命名的子目录,其中包含一个 .sql 文件,用于在该模式中内省的每个视图。每个文件将以单个视图命名,并将包含相关视图定义的查询。

例如,在使用上面使用的模型内省具有默认 public 模式的数据库后,您会发现创建了一个 prisma/views/public/UserInfo.sql 文件,其内容如下

SELECT
u.id,
u.email,
u.name,
p.bio
FROM
(
"User" u
LEFT JOIN "Profile" p ON ((u.id = p."userId"))
);

限制

唯一标识符

目前,Prisma ORM 将视图视为与模型相同的方式。这意味着视图需要至少有一个唯一标识符,可以用以下任何一项表示

  • 使用 @unique 表示的唯一约束
  • 使用 @@unique 表示的复合唯一约束
  • 一个 @id 字段
  • 使用 @@id 表示的复合标识符

在关系数据库中,视图的唯一标识符可以定义为单个字段上的 @unique 属性,或多个字段上的 @@unique 属性。如果可能,最好使用 @unique@@unique 约束而不是 @id@@id 字段。

但是,在 MongoDB 中,唯一标识符必须是一个 @id 属性,该属性使用 @map("_id") 映射到底层数据库中的 _id 字段。

在上面的示例中,id 字段具有 @unique 属性。如果在底层 User 表中的另一个列被定义为唯一可标识的,并且在视图的查询结果中可用,则该列可以用作唯一标识符。

内省

目前,视图的内省仅适用于 PostgreSQL、MySQL、SQL Server 和 CockroachDB。如果您使用其他数据库提供商,则必须手动添加您的视图。

这是一个临时限制,对内省的支持将扩展到其他受支持的数据源提供商。

在 Prisma Client 中查询视图

您可以在 Prisma Client 中以查询模型的方式查询视图。例如,以下查询在上面定义的 UserInfo 视图中查找所有 name'Alice' 的用户。

const userinfo = await prisma.userInfo.findMany({
where: {
name: 'Alice',
},
})

目前,如果底层数据库允许,Prisma Client 允许您更新视图,而无需任何额外的验证。

特殊类型的视图

本节介绍如何在数据库中使用 Prisma ORM 处理可更新视图和物化视图。

可更新视图

某些数据库支持可更新视图(例如PostgreSQLMySQLSQL Server)。可更新视图允许您创建、更新或删除条目。

目前,Prisma ORM 将所有 view 视为可更新视图。如果底层数据库支持视图的此功能,则操作应成功。如果视图未标记为可更新,则数据库将返回错误,Prisma Client 随后将抛出此错误。

将来,Prisma Client 可能会支持将单个视图标记为可更新或不可更新。请在我们的 views 反馈 issue 中评论您的用例。

物化视图

某些数据库支持物化视图,例如 PostgreSQLCockroachDBMongoDBSQL Server(在 SQL Server 中称为“索引视图”)。

物化视图持久化视图查询的结果,以实现更快的访问,并且仅按需更新。

目前,Prisma ORM 不支持物化视图。但是,当您手动创建视图时,您还可以使用底层数据库中的相应命令创建物化视图。然后,您可以使用 Prisma Client 的 TypedSQL 功能 来执行命令并手动刷新视图。

将来,Prisma Client 可能会支持将单个视图标记为物化视图,并添加 Prisma Client 方法来刷新物化视图。请在我们的 views 反馈 issue 中评论您的用例。