跳至主要内容

视图

警告

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

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

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

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

启用 views 预览功能

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

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

请在我们的专用 views 预览功能反馈问题 中留下有关此预览功能的反馈。

在底层数据库中创建视图

目前,您无法使用 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 属性生成,因为 没有定义唯一的标识符(这目前是 视图预览功能的限制)。

警告

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

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

为了能够在 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 视图中所有名为 'Alice' 的用户。

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

目前,Prisma Client 允许您更新视图(如果基础数据库允许),无需任何其他验证。

特殊类型的视图

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

可更新视图

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

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

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

物化视图

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

物化视图会保留视图查询的结果以加快访问速度,并且仅按需更新它。

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

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