视图
数据库视图允许您命名和存储查询。在关系数据库中,视图是存储的 SQL 查询,可能包含多个表中的列,或计算值(例如聚合)。在 MongoDB 中,视图是可查询的对象,其内容由其他集合上的聚合管道定义。
views 预览功能允许您使用 view 关键字在 Prisma schema 中表示视图。要在 Prisma ORM 中使用视图,请按照以下步骤操作
- 启用
views预览功能 - 在底层数据库中创建视图,可以直接创建,也可以手动添加到 Prisma Migrate 迁移文件中,或者使用现有视图
- 在 Prisma schema 中表示视图
- 在 Prisma Client 中查询视图
视图支持目前是一个预览功能。您可以使用 view 关键字将视图添加到 Prisma schema 中,或者使用 db pull 内省数据库 schema 中的视图。您尚无法使用 Prisma Migrate 和 db push 将 schema 中的视图应用到数据库,除非手动使用 --create-only 标志将更改添加到迁移文件中。
有关此功能的最新进展,请关注我们的 GitHub issue。
启用 views 预览功能
视图支持目前处于早期预览阶段。要启用 views 预览功能,请将 views 功能标志添加到 Prisma Schema 中 generator 块的 previewFeatures 字段
generator client {
provider = "prisma-client"
output = "./generated"
previewFeatures = ["views"]
}
请在我们的专用预览功能反馈 issue中留下关于此预览功能的反馈,适用于 views。
在底层数据库中创建视图
目前,您无法使用 Prisma Migrate 或 db push 将 Prisma schema 中定义的视图应用到数据库。相反,您必须首先在底层数据库中手动或作为迁移的一部分创建视图。
例如,以下 Prisma schema 包含一个 User 模型和一个相关的 Profile 模型
- 关系型数据库
- MongoDB
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
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
profile Profile?
}
model Profile {
id String @id @default(auto()) @map("_id") @db.ObjectId
bio String
User User @relation(fields: [userId], references: [id])
userId String @unique @db.ObjectId
}
接下来,在底层数据库中采用一个 UserInfo 视图,该视图结合了 User 模型的 email 和 name 字段以及 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 schema,Prisma ORM 不会创建或运行任何与视图相关的 SQL。
要将视图包含在迁移中,请运行 migrate dev --create-only,然后手动将视图的 SQL 添加到迁移文件中。或者,您可以在数据库中手动创建视图。
将视图添加到 Prisma schema
要将视图添加到 Prisma schema,请使用 view 关键字。
您可以在 Prisma schema 中表示上述示例中的 UserInfo 视图,如下所示
- 关系型数据库
- MongoDB
view UserInfo {
id Int
email String
name String
bio String
}
view UserInfo {
id String @map("_id") @db.ObjectId
email String
name String
bio String
}
手动编写
view 块由两个主要部分组成
view块定义- 视图的字段定义
这两部分允许您在生成的 Prisma Client 中定义视图的名称,以及视图查询结果中存在的列。
定义 view 块
要定义上述示例中的 UserInfo 视图,首先使用 view 关键字在 schema 中定义一个名为 UserInfo 的 view 块
view UserInfo {
// Fields
}
定义字段
视图的属性称为字段,由以下部分组成
- 字段名称
- 字段类型
UserInfo 示例视图的字段可以定义如下
- 关系型数据库
- MongoDB
view UserInfo {
id Int
email String
name String
bio String
}
view UserInfo {
id String @map("_id") @db.ObjectId
email String
name String
bio String
}
view 块的每个字段都表示底层数据库中视图查询结果中的一列。
使用内省
目前,视图只能通过 PostgreSQL、MySQL、SQL Server 和 CockroachDB 数据库进行内省。如果您使用其他数据库提供程序,则必须手动添加视图。
如果您在数据库中定义了一个或多个现有视图,内省将自动在 Prisma schema 中生成表示这些视图的 view 块。
假设示例 UserInfo 视图存在于您的底层数据库中,运行以下命令将在您的 Prisma schema 中生成一个表示该视图的 view 块
npx prisma db pull
生成的 view 块将定义如下
view UserInfo {
id Int?
email String?
name String?
bio String?
}
请注意,目前 db pull 仅在使用 PostgreSQL、MySQL、SQL Server 或 CockroachDB 时内省 schema 中的视图。对其他数据库提供程序的支持将扩展此工作流。
views 目录
内省包含一个或多个现有视图的数据库还将在 prisma 目录中创建一个新的 views 目录(从 Prisma 4.12.0 版本开始)。此目录将包含一个以数据库 schema 命名的子目录,其中包含该 schema 中每个被内省的视图的 .sql 文件。每个文件将以单个视图命名,并将包含相关视图定义的查询。
例如,在使用上面使用的模型内省具有默认 public schema 的数据库后,您会发现创建了一个 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 Client 中查询视图
请务必在更新 Prisma schema 后运行 prisma generate,以便 view 定义成为 Prisma Client API 的一部分。
您可以在 Prisma Client 中以与查询模型相同的方式查询视图。例如,以下查询在上面定义的 UserInfo 视图中查找所有 name 为 'Alice' 的用户。
const userinfo = await prisma.userInfo.findMany({
where: {
name: 'Alice',
},
})
不支持对 views 进行写入查询(创建/更新/删除)。
特殊类型的视图
本节描述如何将 Prisma ORM 与数据库中的可更新视图和物化视图一起使用。
可更新视图
某些数据库支持可更新视图(例如PostgreSQL、MySQL 和 SQL Server)。如果底层数据库支持此类操作,可更新视图允许创建、更新或删除条目。
Prisma ORM 不允许对视图进行任何修改(创建、更新、删除),无论数据库的功能如何。此更改提供了保护措施,以确保视图在 Prisma Client 中始终被视为只读实体。因此,Prisma Client API 中不会为 view 块生成执行写入操作的方法,例如 create、update、delete 或 upsert。
如果您需要修改视图表示的数据,则必须直接对底层表执行写入操作,或使用原始 SQL 查询。
物化视图
某些数据库支持物化视图,例如PostgreSQL、CockroachDB、MongoDB 和 SQL Server(它们被称为“索引视图”)。
物化视图持久化视图查询的结果以实现更快的访问,并且只按需更新。
目前,Prisma ORM 不支持物化视图。但是,当您手动创建视图时,您也可以使用底层数据库中相应的命令创建物化视图。然后,您可以使用 Prisma Client 的TypedSQL 功能执行命令并手动刷新视图。
将来,Prisma Client 可能会支持将单个视图标记为物化视图,并添加 Prisma Client 方法来刷新物化视图。请在我们的 views 反馈 issue 中评论您的用例。
限制
Prisma ORM 将所有 view 块视为数据库查询的只读表示,而不是真正的表。因此,为了确保 Prisma Client 与底层数据库的行为保持一致,存在一些限制。
无标识符
视图是虚拟表,没有固有的主键。因此,您不能在 view 块上定义 @id、@@id 属性。
无索引
由于视图是虚拟表,它们不能有索引。因此,不能在 view 块上定义 @index 和 @@index。
不安全的 @unique 属性
虽然 Prisma ORM 允许您在视图上放置 @unique 和 @@unique 属性,但底层数据库和 Prisma 不强制执行这些约束。因此,多个行可以共享一个应该唯一的字段的相同值。
数据库和 Prisma ORM 都不强制执行该属性表示的唯一约束。
在这种情况下,@unique 属性的目的是仅启用视图之间的关系以及 Prisma Client 中的 findUnique 查询和基于游标的分页。
禁用写入查询
所有写入操作(create、update、delete、upsert)均已禁用,并且未在 Prisma Client 中生成。