Prisma Client API 参考
Prisma Client API 参考文档基于以下 schema
model User {
id Int @id @default(autoincrement())
name String?
email String @unique
profileViews Int @default(0)
role Role @default(USER)
coinflips Boolean[]
posts Post[]
city String
country String
profile ExtendedProfile?
pets Json
}
model ExtendedProfile {
id Int @id @default(autoincrement())
userId Int? @unique
bio String?
User User? @relation(fields: [userId], references: [id])
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(true)
author User @relation(fields: [authorId], references: [id])
authorId Int
comments Json
views Int @default(0)
likes Int @default(0)
}
enum Role {
USER
ADMIN
}
所有示例生成的类型(例如 UserSelect 和 UserWhereUniqueInput)都基于 User 模型。
PrismaClient
本节描述了 PrismaClient 构造函数及其参数。
备注
- 参数在运行时进行验证。
datasources
以编程方式覆盖 schema.prisma 文件中 datasource 块的属性 - 例如,作为集成测试的一部分。另请参阅:数据源
从 5.2.0 版及更高版本开始,您还可以使用 datasourceUrl 属性以编程方式覆盖数据库连接字符串。
属性
| 示例属性 | 示例值 | 描述 |
|---|---|---|
db | { url: 'file:./dev_qa.db' } | 数据库连接 URL。 |
备注
- 每次添加或重命名数据源时,都必须重新生成 Prisma Client。数据源名称包含在生成的客户端中。
- 如果您在 schema 中将
datasource块命名为其他名称,请将db替换为您datasource块的名称。
示例
以编程方式覆盖数据源 url
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({
datasources: {
db: {
url: 'file:./dev_qa.db',
},
},
});
基于以下 datasource 块
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
datasourceUrl
以编程方式覆盖 schema.prisma 文件中的 datasource 块。
属性
| 选项 | 示例值 | 描述 |
|---|---|---|
| 数据库连接字符串 | 'file:./dev_qa.db' | 数据库连接 URL。 |
示例
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({
datasourceUrl: 'postgresql://johndoe:randompassword@localhost:5432/mydb',
});
log
确定日志的类型和级别。另请参阅:日志记录
选项
| 选项 | 示例 |
|---|---|
| 日志级别数组 | [ "info", "query" ] |
| 日志定义数组 | [ { level: "info", emit: "event" }, { level: "warn", emit: "stdout" }] |
日志级别
| 名称 | 示例 |
|---|---|
查询 | 记录 Prisma 运行的所有查询。 对于关系型数据库,这会记录所有 SQL 查询。示例 prisma:query SELECT "public"."User"."id", "public"."User"."email" FROM "public"."User" WHERE ("public"."User"."id") IN (SELECT "t0"."id" FROM "public"."User" AS "t0" INNER JOIN "public"."Post" AS "j0" ON ("j0"."authorId") = ("t0"."id") WHERE ("j0"."views" > $1 AND "t0"."id" IS NOT NULL)) OFFSET $2 对于 MongoDB,这会使用 mongosh shell 格式记录查询。示例prisma:query db.User.deleteMany({ _id: ( $in: [ “6221ce49f756b0721fc00542”, ], }, }) |
信息 | 示例prisma:info Started http server on http://127.0.0.1:58471 |
警告 | 警告。 |
错误 | 错误。 |
发出格式
| 名称 | 描述 |
|---|---|
stdout | 参见:标准输出 |
事件 | 引发您可以订阅的事件。 |
事件类型
query 事件类型
export type QueryEvent = {
timestamp: Date;
query: string; // Query sent to the database
params: string; // Query parameters
duration: number; // Time elapsed (in milliseconds) between client issuing query and database responding - not only time taken to run query
target: string;
};
请注意,对于 MongoDB,params 和 duration 字段将未定义。
所有其他日志级别事件类型
export type LogEvent = {
timestamp: Date;
message: string;
target: string;
};
示例
将 query 和 info 记录到 stdout
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({ log: ['query', 'info'] });
async function main() {
const countUsers = await prisma.user.count({});
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
将 query 事件记录到控制台
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({
log: [{ level: 'query', emit: 'event' }],
});
prisma.$on('query', (e) => {
console.log(e);
});
async function main() {
const countUsers = await prisma.user.count({});
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
将 info、warn 和 error 事件记录到控制台
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({
log: [
{ level: 'warn', emit: 'event' },
{ level: 'info', emit: 'event' },
{ level: 'error', emit: 'event' },
],
});
prisma.$on('warn', (e) => {
console.log(e);
});
prisma.$on('info', (e) => {
console.log(e);
});
prisma.$on('error', (e) => {
console.log(e);
});
async function main() {
const countUsers = await prisma.user.count({});
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
errorFormat
确定 Prisma Client 返回的错误的级别和格式。
错误格式
| 名称 | 描述 |
|---|---|
未定义 | 如果未定义,默认值为无颜色。 |
漂亮 | 启用漂亮的错误格式。 |
colorless (默认) | 启用无颜色错误格式。 |
最小 | 启用最小错误格式。 |
示例
无错误格式
const prisma = new PrismaClient({
// Defaults to colorless
});
pretty 错误格式
const prisma = new PrismaClient({
errorFormat: 'pretty',
});
colorless 错误格式
const prisma = new PrismaClient({
errorFormat: 'colorless',
});
minimal 错误格式
const prisma = new PrismaClient({
errorFormat: 'minimal',
});
adapter
此功能在版本 5.4.0 及更高版本中,并且需要启用 driverAdapters 功能标志。
示例
以下示例使用了 Neon 驱动适配器
import { PrismaNeon } from '@prisma/adapter-neon';
import { PrismaClient } from '@prisma/client';
import dotenv from 'dotenv';
dotenv.config();
const connectionString = `${process.env.DATABASE_URL}`;
const adapter = new PrismaNeon({ connectionString });
const prisma = new PrismaClient({ adapter });
rejectOnNotFound
注意:rejectOnNotFound 在 v5.0.0 中已移除。
已弃用: rejectOnNotFound 在 v4.0.0 中已弃用。从 v4.0.0 开始,请使用查询 findUniqueOrThrow 或 findFirstOrThrow。
使用 rejectOnNotFound 参数配置 findUnique() 和/或 findFirst,以便在未找到记录时抛出错误。默认情况下,如果未找到记录,这两个操作都会返回 null。
备注
- 您可以为
findUnique()和findFirst配置每个请求级别的rejectOnNotFound
选项
| 选项 | 描述 |
|---|---|
未找到时拒绝 | 全局启用(true / false)或抛出自定义错误。 |
每个操作拒绝 | 为每个操作启用(true / false)或为每个模型、每个操作抛出自定义错误。 |
示例
为 findUnique() 和 findFirst 全局启用
const prisma = new PrismaClient({
rejectOnNotFound: true,
});
为特定操作全局启用
const prisma = new PrismaClient({
rejectOnNotFound: {
findUnique: true,
},
});
如果未找到记录,则为每个模型和操作抛出自定义错误
const prisma = new PrismaClient({
rejectOnNotFound: {
findFirst: {
User: (err) => new Error('User error'),
Post: (err) => new Error('Post error!'),
},
findUnique: {
User: (err) => new Error('User error'),
Post: (err) => new Error('Post error!'),
},
},
});
transactionOptions
注意:transactionOptions 在 v5.10.0 中引入。
允许在构造函数级别全局设置事务选项。
备注
- 事务级别可以在每个事务级别被覆盖。
选项
| 选项 | 描述 |
|---|---|
最大等待时间 | Prisma Client 从数据库获取事务的最大等待时间。默认值为 2 秒。 |
超时 | 交互式事务在被取消和回滚之前可以运行的最大时间。默认值为 5 秒。 |
隔离级别 | 设置事务隔离级别。默认情况下,这设置为您数据库中当前配置的值。可用值可能因您使用的数据库而异。 |
示例
const prisma = new PrismaClient({
transactionOptions: {
isolationLevel: Prisma.TransactionIsolationLevel.Serializable,
maxWait: 5000, // default: 2000
timeout: 10000, // default: 5000
},
});
模型查询
使用模型查询对您的模型执行 CRUD 操作。另请参阅:CRUD
注意:最佳实践是在将任何不受信任的用户数据传递到 Prisma 查询之前,始终对其进行验证和清理。否则,如果类型检查被绕过,可能会导致 SQL 注入或其他注入漏洞。确保用户提供的值不能无意中绕过关键检查。我们强烈建议在应用程序层执行类型检查和输入验证。有关更多详细信息,请参阅自定义验证部分。
findUnique()
findUnique() 查询允许您检索单个数据库记录
- 按ID
- 按唯一属性
findUnique() 在 2.12.0 版本中取代了 findOne。
备注
- Prisma Client 的数据加载器自动批处理具有相同
select和where参数的findUnique()查询。 - 如果您希望查询在未找到记录时抛出错误,请考虑改用
findUniqueOrThrow。 - 您不能使用筛选条件(例如
equals、contains、not)来筛选 JSON 数据类型的字段。使用筛选条件可能会导致该字段返回null。
选项
| 名称 | 示例类型(User) | 必需 | 描述 |
|---|---|---|---|
where | UserWhereUniqueInput | 是 | 包装模型的所有字段,以便可以选择记录(了解更多)。 在 4.5.0 版本之前,此类型仅包装模型的唯一字段。 |
select | XOR<UserSelect, null> | 否 | 指定返回对象中要包含的属性。 |
include | XOR<UserInclude, null> | 否 | 指定返回对象中应预加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段 |
关联加载策略 | 'join' 或 'query' | 否 | 默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 对象(有类型) | User | |
| JavaScript 对象(纯文本) | { title: "Hello world" } | 使用 select 和 include 确定要返回的字段。 |
空 | 空 | 未找到记录 |
示例
获取 id 为 42 的 User 记录
const result = await prisma.user.findUnique({
where: {
id: 42,
},
});
获取 email 为 alice@prisma.io 的 User 记录
const result = await prisma.user.findUnique({
where: {
email: 'alice@prisma.io',
},
});
获取 firstName 为 Alice 和 lastName 为 Smith 的 User 记录(@@unique)
展开以查看包含 @@unique 块的示例 User 模型
model User {
firstName String
lastName String
@@unique(fields: [firstName, lastName], name: "fullname")
}
const result = await prisma.user.findUnique({
where: {
fullname: {
// name property of @@unique attribute - default is firstname_lastname
firstName: 'Alice',
lastName: 'Smith',
},
},
});
获取 firstName 为 Alice 和 lastName 为 Smith 的 User 记录(@@id)
展开以查看包含 @@id 块的示例 User 模型
model User {
firstName String
lastName String
@@id([firstName, lastName])
}
const result = await prisma.user.findUnique({
where: {
firstName_lastName: {
firstName: 'Alice',
lastName: 'Smith',
},
},
});
findUniqueOrThrow()
findUniqueOrThrow() 以与 findUnique() 相同的方式检索单个记录。但是,如果查询未找到请求的记录,它会抛出 PrismaClientKnownRequestError。
请注意,在 Prisma v6 之前,它会抛出 NotFoundError: No User found error。
以下是其用法示例
await prisma.user.findUniqueOrThrow({
where: { id: 1 },
});
findUniqueOrThrow() 与 findUnique() 的区别如下
-
其返回类型是非空。例如,
post.findUnique()可以返回post或null,但post.findUniqueOrThrow()始终返回post。 -
它与
$transactionAPI 中的顺序操作不兼容。如果查询抛出PrismaClientKnownRequestError,则 API 不会回滚调用数组中的任何操作。作为变通方法,您可以按如下方式使用带有$transactionAPI 的交互式事务$transaction(async (prisma) => {
await prisma.model.create({ data: { ... });
await prisma.model.findUniqueOrThrow();
})
findFirst()
findFirst 返回列表中符合您条件的第一个记录。
备注
- 如果您希望查询在未找到记录时抛出错误,请考虑改用
findFirstOrThrow。
选项
| 名称 | 示例类型(User) | 必需 | 描述 |
|---|---|---|---|
select | XOR<UserSelect, null> | 否 | 指定返回对象中要包含的属性。 |
include | XOR<UserInclude, null> | 否 | 指定返回对象中应预加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段。 |
关联加载策略 | 'join' 或 'query' | 否 | 默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。 |
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性筛选列表。 |
orderBy | XOR<Enumerable<UserOrderByInput>, UserOrderByInput> | 否 | 允许您按任何属性对返回列表进行排序。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 对象(有类型) | User | 指定要包含在返回对象中的属性。 |
| JavaScript 对象(纯文本) | { title: "Hello world" } | 使用 select 和 include 确定要返回的字段。 |
空 | 空 | 未找到记录 |
备注
findFirst在后台调用findMany并接受相同的查询选项。- 在
findFirst查询中使用负的take值会反转列表的顺序。
示例
请参阅筛选条件和运算符,了解如何筛选结果的示例。
获取 name 为 Alice 的第一个 User 记录
const user = await prisma.user.findFirst({
where: { name: 'Alice' },
});
获取 title 以 A test 开头的第一个 Post 记录,使用 take 反转列表
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({});
async function main() {
const a = await prisma.post.create({
data: {
title: 'A test 1',
},
});
const b = await prisma.post.create({
data: {
title: 'A test 2',
},
});
const c = await prisma.post.findFirst({
where: {
title: {
startsWith: 'A test',
},
},
orderBy: {
title: 'asc',
},
take: -1, // Reverse the list
});
}
main();
findFirstOrThrow()
findFirstOrThrow() 以与 findFirst() 相同的方式检索单个数据记录。但是,如果查询未找到记录,它会抛出 PrismaClientKnownRequestError。
请注意,在 Prisma v6 之前,它会抛出 NotFoundError: No User found error。
findFirstOrThrow() 与 findFirst() 的区别如下
-
其返回类型是非空。例如,
post.findFirst()可以返回post或null,但post.findFirstOrThrow始终返回post。 -
它与
$transactionAPI 中的顺序操作不兼容。如果查询返回PrismaClientKnownRequestError,则 API 不会回滚调用数组中的任何操作。作为变通方法,您可以按如下方式使用带有$transactionAPI 的交互式事务prisma.$transaction(async (tx) => {
await tx.model.create({ data: { ... });
await tx.model.findFirstOrThrow();
})
findMany()
findMany 返回记录列表。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
select | XOR<PostSelect, null> | 否 | 指定返回对象中要包含的属性。 |
include | XOR<PostInclude, null> | 否 | 指定返回对象中应预加载的关系。 |
omit | XOR<PostOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段 |
关联加载策略 | 'join' 或 'query' | 否 | 默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。 |
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性筛选列表。 |
orderBy | XOR<Enumerable<PostOrderByInput>, PostOrderByInput> | 否 | 允许您按任何属性对返回列表进行排序。 |
游标 | UserWhereUniqueInput | 否 | 指定列表的位置(值通常指定 id 或其他唯一值)。 |
take | 数字 | 否 | 指定列表中应返回的对象数量(从列表的开始(正值)或结束(负值)或从指定的 cursor 位置开始计算) |
跳过 | 数字 | 否 | 指定列表中应跳过的返回对象数量。 |
distinct | Enumerable<UserDistinctFieldEnum> | 否 | 允许您按特定字段过滤掉重复行 - 例如,仅返回不重复的 Post 标题。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 数组对象(有类型) | User[] | |
| JavaScript 数组对象(纯文本) | [{ title: "Hello world" }] | 使用 select 和 include 确定要返回的字段。 |
| 空数组 | [] | 未找到匹配记录。 |
示例
请参阅筛选条件和运算符,了解如何筛选结果的示例。
获取所有 name 为 Alice 的 User 记录
const user = await prisma.user.findMany({
where: { name: 'Alice' },
});
create()
create 创建新的数据库记录。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
data | XOR<UserCreateInput, UserUncheckedCreateInput> | 是 | 将所有模型字段包装在类型中,以便在创建新记录时提供它们。它还包括关系字段,允许您执行(事务性)嵌套插入。在数据模型中标记为可选或具有默认值的字段是可选的。 |
select | XOR<UserSelect, null> | 否 | 指定返回对象中要包含的属性。 |
include | XOR<UserInclude, null> | 否 | 指定返回对象中应预加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段 |
关联加载策略 | 'join' 或 'query' | 否 | 默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 对象(有类型) | User | |
| JavaScript 对象(纯文本) | { name: "Alice Wonderland" } | 使用 select 和 include 确定要返回的字段。 |
备注
- 您还可以执行嵌套的
create操作 - 例如,同时添加一个User和两个Post记录。
示例
使用唯一必填字段 email 创建单个新记录
const user = await prisma.user.create({
data: { email: 'alice@prisma.io' },
});
创建多个新记录
在大多数情况下,您可以使用 createMany() 或 createManyAndReturn() 查询执行批量插入。但是,在某些情况下,create() 是插入多条记录的最佳选择。
以下示例会生成两条 INSERT 语句
import { Prisma, PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({ log: ['query'] });
async function main() {
let users: Prisma.UserCreateInput[] = [
{
email: 'ariana@prisma.io',
name: 'Ari',
profileViews: 20,
coinflips: [true, false, false],
role: 'ADMIN',
},
{
email: 'elsa@prisma.io',
name: 'Elsa',
profileViews: 20,
coinflips: [true, false, false],
role: 'ADMIN',
},
];
await Promise.all(
users.map(async (user) => {
await prisma.user.create({
data: user,
});
})
);
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
prisma:query BEGIN
prisma:query INSERT INTO "public"."User" ("name","email","profileViews","role","coinflips") VALUES ($1,$2,$3,$4,$5) RETURNING "public"."User"."id"
prisma:query SELECT "public"."User"."id", "public"."User"."name", "public"."User"."email", "public"."User"."profileViews", "public"."User"."role", "public"."User"."coinflips" FROM "public"."User" WHERE "public"."User"."id" = $1 LIMIT $2 OFFSET $3
prisma:query INSERT INTO "public"."User" ("name","email","profileViews","role","coinflips") VALUES ($1,$2,$3,$4,$5) RETURNING "public"."User"."id"
prisma:query COMMIT
prisma:query SELECT "public"."User"."id", "public"."User"."name", "public"."User"."email", "public"."User"."profileViews", "public"."User"."role", "public"."User"."coinflips" FROM "public"."User" WHERE "public"."User"."id" = $1 LIMIT $2 OFFSET $3
prisma:query COMMIT
update()
update 更新现有数据库记录。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
data | XOR<UserUpdateInputUserUncheckedUpdateInput> | 是 | 将模型的所有字段包装在类型中,以便在更新现有记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
where | UserWhereUniqueInput | 是 | 包装模型的所有字段,以便可以选择记录(了解更多)。 在 4.5.0 版本之前,此类型仅包装模型的唯一字段。 |
select | XOR<UserSelect, null> | 否 | 指定返回对象中要包含的属性。 |
include | XOR<UserInclude, null> | 否 | 指定返回对象中应预加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段。 |
关联加载策略 | 'join' 或 'query' | 否 | 默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 对象(有类型) | User | |
| JavaScript 对象(纯文本) | { name: "Alice Wonderland" } | 使用 select 和 include 确定要返回的字段。 |
RecordNotFound 异常 | 如果记录不存在,则抛出异常。 |
备注
示例
将 id 为 1 的 User 记录的 email 更新为 alice@prisma.io
const user = await prisma.user.update({
where: { id: 1 },
data: { email: 'alice@prisma.io' },
});
upsert()
本节涵盖 upsert() 操作的用法。要了解如何在 update() 中使用 嵌套 upsert 查询,请参阅链接文档。
upsert 执行以下操作
- 如果现有数据库记录满足
where条件,则更新该记录 - 如果没有数据库记录满足
where条件,则创建新的数据库记录
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
创建 | XOR<UserCreateInput,UserUncheckedCreateInput> | 是 | 将模型的所有字段包装在类型中,以便在创建新记录时提供它们。它还包括关系字段,允许您执行(事务性)嵌套插入。在数据模型中标记为可选或具有默认值的字段是可选的。 |
更新 | XOR<UserUpdateInput,UserUncheckedUpdateInput> | 是 | 将模型的所有字段包装在类型中,以便在更新现有记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
where | UserWhereUniqueInput | 是 | 包装模型的所有字段,以便可以选择记录(了解更多)。 在 4.5.0 版本之前,此类型仅包装模型的唯一字段。 |
select | XOR<UserSelect, null> | 否 | 指定返回对象中要包含的属性。 |
include | XOR<UserInclude, null> | 否 | 指定返回对象中应预加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段 |
关联加载策略 | 'join' 或 'query' | 否 | 默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 对象(有类型) | User | |
| JavaScript 对象(纯文本) | { name: "Alice Wonderland" } | 使用 select 和 include 确定要返回的字段。 |
备注
- 要在更新时执行算术运算(加、减、乘、除),请使用原子更新以防止竞态条件。
- 如果同时发生两个或多个 upsert 操作且记录尚不存在,则可能会发生竞态条件。结果,一个或多个 upsert 操作可能会抛出唯一键约束错误。您的应用程序代码可以捕获此错误并重试该操作。了解更多。
- 从 4.6.0 版本开始,Prisma ORM 会尽可能将 upsert 查询交给数据库处理。了解更多。
示例
更新(如果存在)或创建电子邮件为 alice@prisma.io 的新 User 记录
const user = await prisma.user.upsert({
where: { id: 1 },
update: { email: 'alice@prisma.io' },
create: { email: 'alice@prisma.io' },
});
upsert 上的唯一键约束错误
问题
如果同时发生多个 upsert 操作且记录尚不存在,则一个或多个操作可能会返回唯一键约束错误。
原因
当 Prisma Client 执行 upsert 操作时,它首先检查该记录是否已存在于数据库中。为了执行此检查,Prisma Client 使用 upsert 操作中的 where 子句执行读取操作。这有两种可能的结果,如下所示
- 如果记录不存在,则 Prisma Client 创建该记录。
- 如果记录存在,则 Prisma Client 更新它。
当您的应用程序尝试执行两个或更多并发 upsert 操作时,可能会发生竞态条件,即两个或更多操作未找到记录,因此尝试创建该记录。在这种情况下,其中一个操作成功创建新记录,但其他操作失败并返回唯一键约束错误。
解决方案
在您的应用程序代码中处理 P2002 错误。当它发生时,重试 upsert 操作以更新该行。
数据库 upsert
如果可能,Prisma Client 会将 upsert 查询交给数据库处理。这称为数据库 upsert。
数据库 upsert 具有以下优点
- 它们比 Prisma Client 处理的 upsert 更快
- 唯一键约束错误不会发生
当满足特定条件时,Prisma Client 会自动使用数据库 upsert。当不满足这些条件时,Prisma Client 会处理 upsert。
要使用数据库 upsert,Prisma Client 会向数据库发送 SQL 构造 INSERT ... ON CONFLICT SET .. WHERE。
数据库 upsert 前提条件
如果您的技术栈满足以下条件,Prisma Client 可以使用数据库 upsert
- 您使用 Prisma ORM 4.6.0 或更高版本
- 您的应用程序使用 CockroachDB、PostgreSQL 或 SQLite 数据源
数据库 upsert 查询条件
当 upsert 查询满足以下条件时,Prisma Client 会使用数据库 upsert
upsert的create和update选项中没有嵌套查询- 查询不包含使用嵌套读取的选择
- 查询仅修改一个模型
upsert的where选项中只有一个唯一字段where选项中的唯一字段与create选项中的唯一字段具有相同的值
如果您的查询不满足这些条件,则 Prisma Client 会自行处理 upsert。
数据库 upsert 示例
以下示例使用此 schema
model User {
id Int @id
profileViews Int
userName String @unique
email String
@@unique([id, profileViews])
}
以下 upsert 查询满足所有条件,因此 Prisma Client 使用数据库 upsert。
prisma.user.upsert({
where: {
userName: 'Alice',
},
create: {
id: 1,
profileViews: 1,
userName: 'Alice',
email: 'alice@prisma.io',
},
update: {
email: 'updated@example.com',
},
});
在这种情况下,Prisma 使用以下 SQL 查询
INSERT INTO "public"."User" ("id","profileViews","userName","email") VALUES ($1,$2,$3,$4)
ON CONFLICT ("userName") DO UPDATE
SET "email" = $5 WHERE ("public"."User"."userName" = $6 AND 1=1) RETURNING "public"."User"."id", "public"."User"."profileViews", "public"."User"."userName", "public"."User"."email"
以下查询的 where 子句中有多个唯一值,因此 Prisma Client 不使用数据库 upsert
prisma.User.upsert({
where: {
userName: 'Alice',
profileViews: 1,
id: 1,
},
create: {
id: 1,
profileViews: 1,
userName: 'Alice',
email: 'alice@prisma.io',
},
update: {
email: 'updated@example.com',
},
});
在以下查询中,where 和 create 选项中 userName 的值不同,因此 Prisma Client 不使用数据库 upsert。
prisma.User.upsert({
where: {
userName: 'Alice',
},
create: {
id: 1,
profileViews: 1,
userName: 'AliceS',
email: 'alice@prisma.io',
},
update: {
email: 'updated@example.com',
},
});
在以下查询中,posts 中 title 字段的选择是嵌套读取,因此 Prisma Client 不使用数据库 upsert。
prisma.user.upsert({
select: {
email: true,
id: true,
posts: {
select: {
title: true,
},
},
},
where: {
userName: 'Alice',
},
create: {
id: 1,
profileViews: 1,
userName: 'Alice',
email: 'alice@prisma.io',
},
update: {
email: 'updated@example.com',
},
});
delete()
delete 删除现有数据库记录。您可以删除记录
- 按ID
- 按唯一属性
要删除符合特定条件的记录,请使用带有过滤器的 deleteMany。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
where | UserWhereUniqueInput | 是 | 包装模型的所有字段,以便可以选择记录(了解更多)。 在 4.5.0 版本之前,此类型仅包装模型的唯一字段。 |
select | XOR<UserSelect, null> | 否 | 指定返回对象中要包含的属性。 |
include | XOR<UserInclude, null> | 否 | 指定返回对象中应预加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段 |
关联加载策略 | 'join' 或 'query' | 否 | 默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 对象(有类型) | User | 已删除的 User 记录。 |
| JavaScript 对象(纯文本) | { name: "Alice Wonderland" } | 已删除的 User 记录中的数据。使用 select 和 include 确定要返回的字段。 |
RecordNotFound 异常 | 如果记录不存在,则抛出异常。 |
备注
- 要根据某些条件删除多条记录(例如,所有电子邮件地址为
prisma.io的User记录,请使用deleteMany)
示例
删除 id 为 1 的 User 记录
const user = await prisma.user.delete({
where: { id: 1 },
});
删除 email 等于 else@prisma.io 的 User 记录
以下查询删除特定用户记录,并使用 select 返回已删除用户的 name 和 email
const deleteUser = await prisma.user.delete({
where: {
email: 'elsa@prisma.io',
},
select: {
email: true,
name: true,
},
});
{ "email": "elsa@prisma.io", "name": "Elsa" }
createMany()
createMany 在一个事务中创建多条记录。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
data | Enumerable<UserCreateManyInput> | 是 | 将所有模型字段包装在类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
skipDuplicates? | 布尔 | 否 | 不插入具有已存在唯一字段或 ID 字段的记录。仅受支持 ON CONFLICT DO NOTHING 的数据库支持。这不包括 MongoDB 和 SQLServer |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
BatchPayload | { count: 3 } | 创建的记录数量。 |
备注
- 自 Prisma ORM 5.12.0 版本起,SQLite 现已支持
createMany()。 - MongoDB、SQLServer 或 SQLite 不支持
skipDuplicates选项。 - 您不能通过在顶级
createMany()查询中使用嵌套的create、createMany、connect、connectOrCreate查询来创建或连接关系。请参阅此处以获取解决方法。 - 您可以在
update()或create()查询中嵌套使用createMany查询 - 例如,同时添加一个User和两个Post记录,并进行嵌套的createMany。
示例
创建多个新用户
const users = await prisma.user.createMany({
data: [
{ name: 'Sonali', email: 'sonali@prisma.io' },
{ name: 'Alex', email: 'alex@prisma.io' },
],
});
createManyAndReturn()
createManyAndReturn 创建多条记录并返回结果对象。
此功能在 Prisma ORM 5.14.0 及更高版本中可用,适用于 PostgreSQL、CockroachDB 和 SQLite。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
data | Enumerable<UserCreateManyInput> | 是 | 将所有模型字段包装在类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
select | XOR<UserSelect, null> | 否 | 指定要在返回对象中包含的属性。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段。与 select 互斥。 |
include | XOR<UserInclude, null> | 否 | 指定在返回对象中应预加载哪些关系。 |
skipDuplicates? | 布尔 | 否 | 不插入具有已存在唯一字段或 ID 字段的记录。仅受支持 ON CONFLICT DO NOTHING 的数据库支持。这不包括 MongoDB 和 SQLServer |
备注
- SQLite 不支持
skipDuplicates选项。 - 请注意,
createManyAndReturn返回的元素顺序不保证。 - 您不能通过在顶级
createManyAndReturn()查询中嵌套使用create、createMany、connect、connectOrCreate查询来创建或连接关系。请参阅此处以获取解决方法。 - 当关系通过
include包含时,会为每个关系生成一个单独的查询。 - 不支持
relationLoadStrategy: join。
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 数组对象(有类型) | User[] | |
| JavaScript 数组对象(纯文本) | [{ name: "Sonali" }] | 使用 select、omit 和 include 确定要返回的字段。 |
示例
创建并返回多个新用户
const users = await prisma.user.createManyAndReturn({
data: [
{ name: 'Sonali', email: 'sonali@prisma.io' },
{ name: 'Alex', email: 'alex@prisma.io' },
],
})
[
{ "id": 0, "name": "Sonali", "email": "sonali@prisma.io", "profileViews": 0 },
{ "id": 1, "name": "Alex", "email": "alex@prisma.io", "profileViews": 0 }
]
updateMany()
updateMany 批量更新现有数据库记录并返回更新的记录数量。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
data | XOR<UserUpdateManyMutationInput,UserUncheckedUpdateManyInput> | 是 | 将模型的所有字段包装在类型中,以便在更新现有记录时提供它们。在数据模型中标记为可选或具有默认值的字段在 data 上是可选的。 |
where | UserWhereInput | 否 | 将模型的所有字段包装在类型中,以便可以通过任何属性过滤列表。如果您不过滤列表,则所有记录都将被更新。 |
限制 | 数字 | 否 | 限制更新的记录数量。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
BatchPayload | { count: 4 } | 已更新记录的数量。 |
export type BatchPayload = {
count: number;
};
示例
将所有 name 为 Alice 的 User 记录更新为 ALICE
const updatedUserCount = await prisma.user.updateMany({
where: { name: 'Alice' },
data: { name: 'ALICE' },
});
更新所有 email 包含 prisma.io 且至少一篇相关 Post 点赞数超过 10 的 User 记录
const updatedUserCount = await prisma.user.updateMany({
where: {
email: {
contains: 'prisma.io',
},
posts: {
some: {
likes: {
gt: 10,
},
},
},
},
data: {
role: 'USER',
},
});
更新 email 包含 prisma.io 的 User 记录,但限制更新 5 条记录。
const updatedUserCount = await prisma.user.updateMany({
where: {
email: {
contains: 'prisma.io',
},
},
data: {
role: 'USER',
},
limit: 5,
});
updateManyAndReturn()
此功能在 Prisma ORM 6.2.0 及更高版本中可用,适用于 PostgreSQL、CockroachDB 和 SQLite。
updateManyAndReturn 更新多条记录并返回结果对象。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
data | XOR<UserUpdateManyMutationInput,UserUncheckedUpdateManyInput> | 是 | 将模型的所有字段包装在类型中,以便在更新现有记录时提供它们。在数据模型中标记为可选或具有默认值的字段在 data 上是可选的。 |
where | UserWhereInput | 否 | 将模型的所有字段包装在类型中,以便可以通过任何属性过滤列表。如果您不过滤列表,则所有记录都将被更新。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
| JavaScript 数组对象(有类型) | User[] | |
| JavaScript 数组对象(纯文本) | [{ name: "Sonali" }] | 使用 select、omit 和 include 确定要返回的字段。 |
示例
更新并返回多个用户
const users = await prisma.user.updateManyAndReturn({
where: {
email: {
contains: 'prisma.io',
}
},
data: {
role: 'ADMIN'
},
})
[
{ "id": 0, "name": "Sonali", "email": "sonali@prisma.io", "role": "ADMIN", "profileViews": 0 },
{ "id": 1, "name": "Alex", "email": "alex@prisma.io", "role": "ADMIN", "profileViews": 0 }
]
deleteMany()
deleteMany 在一个事务中删除多条记录。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
where | UserWhereInput | 否 | 将模型的所有字段包装在类型中,以便可以通过任何字段进行筛选。 |
限制 | 整数 | 否 | 限制删除的记录数量。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
BatchPayload | { count: 4 } | 已删除记录的数量。 |
export type BatchPayload = {
count: number;
};
示例
删除所有 User 记录
const deletedUserCount = await prisma.user.deleteMany({});
删除所有 name 为 Alice 的 User 记录
const deletedUserCount = await prisma.user.deleteMany({
where: { name: 'Alice' },
});
删除所有 email 包含 prisma.io 的 User 记录,但限制删除 5 条记录。
const deletedUserCount = await prisma.user.deleteMany({
where: {
email: {
contains: 'prisma.io',
},
},
limit: 5,
});
请参阅筛选条件和运算符,了解如何筛选要删除的记录的示例。
count()
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性筛选列表。 |
orderBy | XOR<Enumerable<PostOrderByInput>, PostOrderByInput> | 否 | 允许您按任何属性对返回列表进行排序。 |
游标 | UserWhereUniqueInput | 否 | 指定列表的位置(值通常指定 id 或其他唯一值)。 |
take | 数字 | 否 | 指定列表中应返回的对象数量(从列表的开始(正值)或结束(负值)或从指定的 cursor 位置开始计算) |
跳过 | 数字 | 否 | 指定列表中应跳过的返回对象数量。 |
返回类型
| 返回类型 | 示例 | 描述 |
|---|---|---|
数字 | 29 | 记录的数量。 |
UserCountAggregateOutputType | { _all: 27, name: 10 } | 如果使用了 select 则返回。 |
示例
统计所有 User 记录
const result = await prisma.user.count();
统计所有至少有一篇已发布 Post 的 User 记录
const result = await prisma.user.count({
where: {
post: {
some: {
published: true,
},
},
},
});
使用 select 执行三个独立的计数
以下查询返回
- 所有记录的数量 (
_all) - 所有
name字段非null的记录的数量 - 所有
city字段非null的记录的数量
const c = await prisma.user.count({
select: {
_all: true,
city: true,
name: true,
},
});
aggregate()
另请参阅:聚合、分组和汇总
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性筛选列表。 |
orderBy | XOR<Enumerable<UserOrderByInput>,UserOrderByInput> | 否 | 允许您按任何属性对返回列表进行排序。 |
游标 | UserWhereUniqueInput | 否 | 指定列表的位置(值通常指定 id 或其他唯一值)。 |
take | 数字 | 否 | 指定列表中应返回的对象数量(从列表的开始(正值)或结束(负值)或从指定的 cursor 位置开始计算) |
跳过 | 数字 | 否 | 指定列表中应跳过的返回对象数量。 |
_count | 真 | 否 | 返回匹配记录或非 null 字段的计数。 |
_avg | UserAvgAggregateInputType | 否 | 返回指定字段所有值的平均值。 |
_sum | UserSumAggregateInputType | 否 | 返回指定字段所有值的总和。 |
_min | UserMinAggregateInputType | 否 | 返回指定字段的最小可用值。 |
_max | UserMaxAggregateInputType | 否 | 返回指定字段的最大可用值。 |
示例
返回所有 User 记录的 profileViews 的 _min、_max 和 _count
const minMaxAge = await prisma.user.aggregate({
_count: {
_all: true,
},
_max: {
profileViews: true,
},
_min: {
profileViews: true,
},
});
返回所有 User 记录的 profileViews 的 _sum
const setValue = await prisma.user.aggregate({
_sum: {
profileViews: true,
},
});
groupBy()
另请参阅:聚合、分组和汇总
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性筛选列表。 |
orderBy | XOR<Enumerable<UserOrderByInput>,UserOrderByInput> | 否 | 允许您根据 by 中也存在的任何属性对返回列表进行排序。 |
by | Array<UserScalarFieldEnum> | string | 否 | 指定用于分组记录的字段或字段组合。 |
having | UserScalarWhereWithAggregatesInput | 否 | 允许您按聚合值过滤组 - 例如,仅返回平均年龄小于 50 的组。 |
take | 数字 | 否 | 指定列表中应返回的对象数量(从列表的开始(正值)或结束(负值)或从指定的 cursor 位置开始计算) |
跳过 | 数字 | 否 | 指定列表中应跳过的返回对象数量。 |
_count | true | UserCountAggregateInputType | 否 | 返回匹配记录或非 null 字段的计数。 |
_avg | UserAvgAggregateInputType | 否 | 返回指定字段所有值的平均值。 |
_sum | UserSumAggregateInputType | 否 | 返回指定字段所有值的总和。 |
_min | UserMinAggregateInputType | 否 | 返回指定字段的最小可用值。 |
_max | UserMaxAggregateInputType | 否 | 返回指定字段的最大可用值。 |
示例
按 country/city 分组,其中平均 profileViews 大于 200,并返回每个组的 profileViews 的 _sum
该查询还返回每个组中 _all 记录的计数,以及每个组中 city 字段值非 null 的所有记录。
const groupUsers = await prisma.user.groupBy({
by: ['country', 'city'],
_count: {
_all: true,
city: true,
},
_sum: {
profileViews: true,
},
orderBy: {
country: 'desc',
},
having: {
profileViews: {
_avg: {
gt: 200,
},
},
},
});
[
{
country: 'Denmark',
city: 'Copenhagen',
_sum: { profileViews: 490 },
_count: {
_all: 70,
city: 8,
},
},
{
country: 'Sweden',
city: 'Stockholm',
_sum: { profileViews: 500 },
_count: {
_all: 50,
city: 3,
},
},
];
findRaw()
aggregateRaw()
模型查询选项
select
select 定义 Prisma Client 返回的对象中包含哪些字段。参见:选择字段并包含关系。
备注
- 您不能在同一级别同时使用
select和include。 - 在 3.0.1 及更高版本中,您可以选择关系的
_count。
示例
选择单个 User 记录的 name 和 profileViews 字段
const result = await prisma.user.findUnique({
where: { id: 1 },
select: {
name: true,
profileViews: true,
},
});
选择多个 User 记录的 email 和 role 字段
const result = await prisma.user.findMany({
select: {
email: true,
role: true,
},
});
选择关系的 _count
const usersWithCount = await prisma.user.findMany({
select: {
_count: {
select: { posts: true },
},
},
});
选择相关 Post 记录的 'id' 和 'title' 字段
const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
select: {
id: true,
title: true,
},
},
},
});
select 中的 include
const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
include: {
author: true,
},
},
},
});
select 的生成类型
以下示例演示了如何将 validator 与 select 一起使用
const selectNameEmailNotPosts = Prisma.validator<Prisma.UserSelect>()({
name: true,
email: true,
posts: false,
});
include
include 定义了 Prisma Client 返回的结果中包含哪些关系。参见:选择字段并包含关系。
备注
- 在 3.0.1 及更高版本中,您可以
include关系的_count
示例
在加载 User 记录时包含 posts 和 profile 关系
const users = await prisma.user.findMany({
include: {
posts: true, // Returns all fields for all posts
profile: true, // Returns all Profile fields
},
});
在创建包含两条 Post 记录的新 User 记录时,在返回的对象中包含 posts 关系
const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
posts: {
create: [{ title: 'This is my first post' }, { title: 'Here comes a second post' }],
},
},
include: { posts: true }, // Returns all fields for all posts
});
include 的生成类型
以下示例演示了如何将 validator 与 include 一起使用
const includePosts = Prisma.validator<Prisma.UserInclude>()({
posts: true,
});
包含关系的 _count
const usersWithCount = await prisma.user.findMany({
include: {
_count: {
select: { posts: true },
},
},
});
omit
omit 定义了 Prisma Client 返回的对象中排除哪些字段。
备注
- 您不能同时使用
omit和select,因为它们的目的相反 omit随 Prisma ORM 6.2.0 发布到通用版本。在 Prisma ORM5.13.0到6.1.0版本中,它通过omitApi预览功能提供。
示例
从所有 User 记录中省略 password 字段
const result = await prisma.user.findMany({
omit: {
password: true,
},
});
从所有 User 的 posts 关系中省略 title 字段
const results = await prisma.user.findMany({
omit: {
password: true,
},
include: {
posts: {
omit: {
title: true,
},
},
},
});
omit 的生成类型
以下示例演示了如何将 validator 与 omit 一起使用
const omitPassword = Prisma.validator<Prisma.UserOmit>()({
password: true,
});
relationLoadStrategy(预览)
relationLoadStrategy 指定如何从数据库加载关系。它有两个可能的值
join(默认):使用数据库级别的LATERAL JOIN(PostgreSQL)或相关子查询(MySQL),并通过单个查询从数据库获取所有数据。query:向数据库发送多个查询(每个表一个),并在应用程序级别进行连接。
注意:一旦
relationLoadStrategy从预览阶段进入通用可用阶段,join将普遍成为所有关系查询的默认值。
您可以在此处了解有关连接策略的更多信息。
由于 relationLoadStrategy 选项目前处于预览阶段,您需要在 Prisma schema 文件中通过 relationJoins 预览功能标志启用它
generator client {
provider = "prisma-client-js"
previewFeatures = ["relationJoins"]
}
添加此标志后,您需要再次运行 prisma generate 以重新生成 Prisma Client。relationJoins 功能目前在 PostgreSQL、CockroachDB 和 MySQL 上可用。
备注
- 在大多数情况下,默认的
join策略会更有效。如果您想节省数据库服务器上的资源,或者如果您的性能分析显示应用程序级连接性能更好,请使用query。 - 您只能在查询的顶层指定
relationLoadStrategy。顶层选择将影响所有嵌套的子查询。
示例
使用 include 时,通过数据库级别 JOIN 加载 posts 关系
const users = await prisma.user.findMany({
relationLoadStrategy: 'join',
include: {
posts: true,
},
});
使用 select 时,通过数据库级别 JOIN 加载 posts 关系
const users = await prisma.user.findMany({
relationLoadStrategy: 'join',
select: {
posts: true,
},
});
where
where 定义一个或多个过滤器,可用于筛选记录属性(如用户的电子邮件地址)或相关记录属性(如用户最近 10 篇最热门帖子标题)。
示例
const results = await prisma.user.findMany({
where: {
email: {
endsWith: 'prisma.io',
},
},
});
where 的生成类型
以下示例演示了如何将 validator 与 where 一起使用
-
UserWhereInput// UserWhereInput
const whereNameIs = Prisma.validator<Prisma.UserWhereInput>()({
name: 'Rich',
});
// It can be combined with conditional operators too
const whereNameIs = Prisma.validator<Prisma.UserWhereInput>()({
name: 'Rich',
AND: [
{
email: {
contains: 'rich@boop.com',
},
},
],
}); -
UserWhereUniqueInput此类型通过公开模型上的任何唯一字段来工作。被指定为@id的字段被认为是唯一的,被指定为@unique的字段也是如此。从 4.5.0 版本开始,此类型公开模型上的所有字段。这意味着当您根据唯一字段筛选单个记录时,您可以同时检查额外的非唯一字段和唯一字段。 了解更多。
// UserWhereUniqueInput
const whereEmailIsUnique = Prisma.validator<Prisma.UserWhereUniqueInput>()({
email: 'rich@boop.com',
}) -
PostScalarWhereInputconst whereScalarTitleIs = Prisma.validator<Prisma.PostScalarWhereInput>()({
title: 'boop',
}); -
PostUpdateWithWhereUniqueWithoutAuthorInput- 此类型接受一个唯一的where字段(一个@id或另一个指定的@unique),并更新Post模型上除Author之外的任何字段。Author是Post模型上的标量字段。const updatePostByIdWithoutAuthor =
Prisma.validator<Prisma.PostUpdateWithWhereUniqueWithoutAuthorInput>()({
where: {
id: 1,
},
data: {
content: 'This is some updated content',
published: true,
title: 'This is a new title',
},
}); -
PostUpsertWithWhereUniqueWithoutAuthorInput- 此类型将更新Post记录的标题字段,其中 id 匹配,如果不存在则会创建它。const updatePostTitleOrCreateIfNotExist =
Prisma.validator<Prisma.PostUpsertWithWhereUniqueWithoutAuthorInput>()({
where: {
id: 1,
},
update: {
title: 'This is a new title',
},
create: {
id: 1,
title: 'If the title doesnt exist, then create one with this text',
},
}); -
PostUpdateManyWithWhereWithoutAuthorInput- 此类型将更新所有Post记录,其中 published 设置为 false。const publishAllPosts = Prisma.validator<Prisma.PostUpdateManyWithWhereWithoutAuthorInput>()({
where: {
published: {
equals: false,
},
},
data: {
published: true,
},
});
orderBy
对记录列表进行排序。另请参阅:排序
备注
-
在 4.1.0 及更高版本中,您可以将
null记录排在最前或最后。欲了解详情,请参阅将 null 值排在最前或最后。
sort 参数的输入
| 名称 | 描述 |
|---|---|
asc | 升序排序(A → Z) |
desc | 降序排序(Z → A) |
nulls 参数的输入
注意
- 此参数是可选的。
- 它仅用于可选的标量字段。如果您尝试在必填或关联字段上按 null 值排序,Prisma Client 将抛出 P2009 错误。
- 此功能在 4.1.0 及更高版本中可用,作为预览功能。有关如何启用此功能的详细信息,请参阅将 null 值排在最前或最后。
| 名称 | 描述 |
|---|---|
first | 将 null 值排在最前。 |
last | 将 null 值排在最后。 |
示例
按 email 字段排序 User
以下示例返回所有按 email 升序排序的 User 记录
const users = await prisma.user.findMany({
orderBy: {
email: 'asc',
},
});
以下示例返回所有按 email 降序排序的 User 记录
const users = await prisma.user.findMany({
orderBy: {
email: 'desc',
},
});
按关联的 User 记录的 name 排序 Post
以下查询按用户姓名排序帖子
const posts = await prisma.post.findMany({
orderBy: {
author: {
name: 'asc',
},
},
});
按关联的 User 记录的 name 排序 Post,null 记录优先
以下查询按用户姓名排序帖子,null 记录优先
const posts = await prisma.post.findMany({
orderBy: {
author: {
name: { sort: 'asc', nulls: 'first' },
},
},
});
按标题相关性排序 Post
对于 PostgreSQL,此功能仍处于预览阶段。要使用它,请启用 fullTextSearchPostgres 功能标志。
以下查询按搜索词 'database' 与标题的相关性对帖子进行排序
const posts = await prisma.post.findMany({
orderBy: {
_relevance: {
fields: ['title'],
search: 'database',
sort: 'asc'
},
})
按 posts 数量排序 User
以下查询按帖子数量排序用户
const getActiveusers = await prisma.user.findMany({
orderBy: {
posts: {
count: 'desc',
},
},
});
按多个字段排序 User - email 和 role
以下示例按两个字段排序用户 - 首先是 email,然后是 role
const users = await prisma.user.findMany({
select: {
email: true,
role: true,
},
orderBy: [
{
email: 'desc',
},
{
role: 'desc',
},
],
});
排序参数的顺序很重要 - 以下查询按 role 排序,然后按 email 排序。注意结果差异
const users = await prisma.user.findMany({
select: {
email: true,
role: true,
},
orderBy: [
{
role: 'desc',
},
{
email: 'desc',
},
],
});
按 email 排序 User,选择 name 和 email
以下示例返回所有 User 记录的 name 和 email 字段,按 email 排序
const users3 = await prisma.user.findMany({
orderBy: {
email: 'asc',
},
select: {
name: true,
email: true,
},
});
按 email 排序 User 记录并按 title 排序嵌套的 Post 记录
以下示例
- 返回所有按
email排序的User记录 - 对于每个
User记录,返回所有按title排序的嵌套Post记录的title字段
const usersWithPosts = await prisma.user.findMany({
orderBy: {
email: 'asc',
},
include: {
posts: {
select: {
title: true,
},
orderBy: {
title: 'asc',
},
},
},
});
排序单个用户的嵌套 Post 记录列表
以下示例通过 ID 检索单个 User 记录,以及按 title 排序的嵌套 Post 记录列表
const userWithPosts = await prisma.user.findUnique({
where: {
id: 1,
},
include: {
posts: {
orderBy: {
title: 'desc',
},
select: {
title: true,
published: true,
},
},
},
});
按 enum 排序
以下按 role(一个 enum)排序所有 User 记录
const sort = await prisma.user.findMany({
orderBy: {
role: 'desc',
},
select: {
email: true,
role: true,
},
});
orderBy 的生成类型
以下示例演示了如何将 validator 与 orderBy 一起使用
UserOrderByInputconst orderEmailsByDescending = Prisma.validator<Prisma.UserOrderByInput>()({
email: 'desc',
});
distinct
从 findMany 或 findFirst 中去除记录列表的重复项。另请参阅:聚合、分组和汇总
示例
在单个字段上选择 distinct
以下示例返回所有不同的 city 字段,并且只选择 city 和 country 字段
const distinctCities = await prisma.user.findMany({
select: {
city: true,
country: true,
},
distinct: ['city'],
});
[
{ city: 'Paris', country: 'France' },
{ city: 'Lyon', country: 'France' },
];
在多个字段上选择 distinct
以下示例返回所有不同的 city 和 country 字段组合,并且只选择 city 和 country 字段
const distinctCitiesAndCountries = await prisma.user.findMany({
select: {
city: true,
country: true,
},
distinct: ['city', 'country'],
});
[
{ city: 'Paris', country: 'France' },
{ city: 'Paris', country: 'Denmark' },
{ city: 'Lyon', country: 'France' },
];
请注意,除了“法国巴黎”之外,现在还有“丹麦巴黎”
结合过滤器选择 distinct
以下示例返回所有不同的 city 和 country 字段组合,其中用户电子邮件包含 "prisma.io",并且只选择 city 和 country 字段
const distinctCitiesAndCountries = await prisma.user.findMany({
where: {
email: {
contains: 'prisma.io',
},
},
select: {
city: true,
country: true,
},
distinct: ['city', 'country'],
});
nativeDistinct
在您的 Prisma schema 中启用 nativeDistinct 会将 distinct 操作推送到数据库层(如果支持)。这可以显著提高性能。但是,请注意
- 某些数据库可能不完全支持特定字段组合上的 DISTINCT。
- 不同提供商的行为可能有所不同。
要启用 nativeDistinct
generator client {
provider = "prisma-client-js"
previewFeatures = ["nativeDistinct"]
}
有关详细信息,请参阅预览功能。
嵌套查询
create
嵌套 create 查询会将一条或一组新的相关记录添加到父记录。请参阅:处理关系
备注
- 当您
create()(prisma.user.create(...)) 一个新的父记录或update()(prisma.user.update(...)) 一个现有父记录时,create可作为嵌套查询使用。 - 您可以使用嵌套的
create或 嵌套的createMany来创建多个相关记录。如果需要skipDuplicates查询选项,您应该使用createMany。
示例
创建包含新 Profile 记录的新 User 记录
const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
profile: {
create: { bio: 'Hello World' },
},
},
});
创建包含新 User 记录的新 Profile 记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
create: { email: 'alice@prisma.io' },
},
},
})
创建包含新 Post 记录的新 User 记录
const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
posts: {
create: { title: 'Hello World' },
},
},
});
创建包含两条新 Post 记录的新 User 记录
因为这是一对多关系,您还可以通过向 create 传递一个数组来一次性创建多个 Post 记录
const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
posts: {
create: [
{
title: 'This is my first post',
},
{
title: 'Here comes a second post',
},
],
},
},
});
注意:您也可以使用嵌套的 createMany 来实现相同的结果。
通过创建新的 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
create: { bio: 'Hello World' },
},
},
});
通过创建新的 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
create: { title: 'Hello World' },
},
},
})
createMany
嵌套 createMany 查询会将一组新的记录添加到父记录。请参阅:处理关系
备注
- 当您
create()(prisma.user.create(...)) 一个新的父记录或update()(prisma.user.update(...)) 一个现有父记录时,createMany可作为嵌套查询使用。- 在一对多关系的上下文中可用 — 例如,您可以
prisma.user.create(...)一个用户并使用嵌套的createMany来创建多个帖子(帖子有一个用户)。 - 在多对多关系的上下文中不可用 — 例如,您不能
prisma.post.create(...)一个帖子并使用嵌套的createMany来创建类别(许多帖子有许多类别)。
- 在一对多关系的上下文中可用 — 例如,您可以
- 您不能再嵌套一个
create或createMany。 - 允许直接设置外键 — 例如,设置帖子的
categoryId。 - 从 Prisma ORM 5.12.0 版本开始,SQLite 支持嵌套的
createMany。 - 您可以使用嵌套的
create或 嵌套的createMany来创建多个相关记录 - 如果您不需要skipDuplicates查询选项,您可能应该使用create。
选项
| 名称 | 类型 | 必需 | 描述 |
|---|---|---|---|
data | Enumerable<UserCreateManyInput> | 是 | 将所有模型字段包装在类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
skipDuplicates? | 布尔 | 否 | 不插入具有已存在唯一字段或 ID 字段的记录。仅受支持 ON CONFLICT DO NOTHING 的数据库支持。这不包括 MongoDB 和 SQLServer |
示例
更新 User 和多个新的相关 Post 记录
const user = await prisma.user.update({
where: {
id: 9,
},
data: {
name: 'Elliott',
posts: {
createMany: {
data: [{ title: 'My first post' }, { title: 'My second post' }],
},
},
},
});
set
set 覆盖关系的当前值 — 例如,用不同的列表替换 Post 记录列表。请参阅:处理关系
示例
通过断开任何先前的 Post 记录并连接两条其他现有记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
set: [{ id: 32 }, { id: 42 }],
},
},
});
connect
嵌套 connect 查询通过指定 ID 或唯一标识符将记录连接到现有相关记录。请参阅:处理关系
备注
-
当您创建新的父记录或更新现有父记录时,
connect可作为嵌套查询使用。 -
如果相关记录不存在,Prisma Client 将抛出异常
The required connected records were not found. Expected 1 records to be connected, found 0. -
当同时使用
set和connect时,它们的应用顺序会显著影响结果。如果在connect之前使用set,则连接的记录将只反映connect操作建立的最终状态,因为set会在connect建立新连接之前清除所有现有连接。反之,如果在set之前应用connect,则set操作将通过清除所有已连接的记录并将其替换为自身指定的状态来覆盖connect操作。
示例
创建新的 Profile 记录并通过唯一字段将其连接到现有 User 记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
connect: { email: 'alice@prisma.io' },
},
},
});
创建新的 Profile 记录并通过 ID 字段将其连接到现有 User 记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
connect: { id: 42 }, // sets userId of Profile record
},
},
});
在 2.11.0 及更高版本中,您可以直接设置外键
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
userId: 42,
},
});
但是,您不能在同一查询中同时使用直接方法和 connect 方法。有关详细信息,请参阅此问题评论。
创建新的 Post 记录并将其连接到现有 User 记录
const user = await prisma.post.create({
data: {
title: 'Hello World',
author: {
connect: { email: 'alice@prisma.io' },
},
},
});
通过连接到现有 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
connect: { id: 24 },
},
},
});
通过连接到两条现有 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
connect: [{ id: 24 }, { id: 42 }],
},
},
});
connectOrCreate
connectOrCreate 要么 通过 ID 或唯一标识符将记录连接到现有相关记录,要么 在记录不存在时创建新的相关记录。请参阅:处理关系
备注
-
同时运行的多个
connectOrCreate查询(作为并发事务)可能导致竞态条件。考虑以下示例,其中两个查询试图同时connectOrCreate名为computing的博客文章标签(标签名称必须是唯一的)- 查询 A
- 查询 B
const createPost = await prisma.post.create({
data: {
title: 'How to create a compiler',
content: '...',
author: {
connect: {
id: 9,
},
},
tags: {
connectOrCreate: {
create: {
name: 'computing',
},
where: {
name: 'computing',
},
},
},
},
})const createPost = await prisma.post.create({
data: {
title: 'How to handle schema drift in production',
content: '...',
author: {
connect: {
id: 15,
},
},
tags: {
connectOrCreate: {
create: {
name: 'computing',
},
where: {
name: 'computing',
},
},
},
},
})如果查询 A 和查询 B 以以下方式重叠,则查询 A 会导致异常
查询 A (失败 ❌) 查询 B (成功 ✅) 查询到达服务器,开始事务 A 查询到达服务器,开始事务 B 查找 tagName等于computing的记录,未找到记录查找 tagName等于computing的记录,未找到记录创建 tagName等于computing的记录并连接创建 tagName等于computing的记录唯一性冲突,记录已被事务 B 创建 为了解决这种情况,我们建议捕获唯一性冲突异常(
PrismaClientKnownRequestError,错误代码P2002)并重试失败的查询。
示例
创建新的 Profile 记录,然后将其连接到现有 User 记录或创建新的 User
以下示例
- 创建一个
Profile - 尝试将 profile 连接到电子邮件地址为
alice@prisma.io的User - 如果匹配的用户不存在,则创建一个新用户
const user = await prisma.profile.create({
data: {
bio: 'The coolest Alice on the planet',
user: {
connectOrCreate: {
where: { email: 'alice@prisma.io' },
create: { email: 'alice@prisma.io'}
},
},
})
创建新的 Post 记录并将其连接到现有 User 记录,或创建新的 User
const user = await prisma.post.create({
data: {
title: 'Hello World',
author: {
connectOrCreate: {
where: { email: 'alice@prisma.io' },
create: { email: 'alice@prisma.io' },
},
},
},
});
通过连接到现有 Profile 记录或创建新的 Profile 记录来更新现有 User 记录
以下示例
- 尝试将用户连接到
id为20的Profile - 如果匹配的 profile 不存在,则创建一个新 profile
const updateUser = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
connectOrCreate: {
where: { id: 20 },
create: {
bio: 'The coolest Alice in town',
},
},
},
},
});
通过连接到两条现有 Post 记录或创建两条新 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
connectOrCreate: [
{
where: { id: 32 },
create: { title: 'This is my first post' },
},
{
where: { id: 19 },
create: { title: 'This is my second post' },
},
],
},
},
});
disconnect
嵌套 disconnect 查询会中断父记录和相关记录之间的连接,但不会删除任何记录。请参阅:处理关系
备注
-
disconnect仅在关系是可选时可用。 -
如果您尝试断开的关系不存在
-
(在 2.21.0 及更高版本中),该操作不做任何事情
-
(在 2.21.0 之前)如果提供的 ID 或唯一标识符未连接,Prisma Client 将抛出异常
The records for relation `PostToUser` between the `User` and `Post` models are not connected.
-
示例
通过断开与 Profile 记录的连接来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'bob@prisma.io' },
data: {
profile: {
disconnect: true,
},
},
});
通过断开与两条 Post 记录的连接来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
disconnect: [{ id: 44 }, { id: 46 }],
},
},
});
update
嵌套的 update 查询会更新一个或多个相关记录,其中父记录的 ID 为 n。请参阅:处理关系
备注
-
嵌套的
update查询仅在顶级update查询的上下文中可用(例如,prisma.user.update(...))。 -
如果父记录不存在,Prisma Client 将抛出异常
AssertionError("Expected a valid parent ID to be present for nested update to-one case.") -
如果您想要更新的相关记录不存在,Prisma Client 将抛出异常
AssertionError("Expected a valid parent ID to be present for nested update to-one case.")
示例
通过更新所连接的 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
update: { bio: 'Hello World' },
},
},
});
通过更新所连接的两条 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
update: [
{
data: { published: true },
where: { id: 32 },
},
{
data: { published: true },
where: { id: 23 },
},
],
},
},
});
upsert
本节介绍 update() 中嵌套 upsert 的用法。要了解 upsert() 操作,请参考链接的文档。
嵌套的 upsert 查询会在相关记录存在时更新它,或者在不存在时创建新的相关记录。
示例
通过更新现有 User 记录所连接的 Profile 记录或创建新记录来更新现有 User 记录(upsert)
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
upsert: {
create: { bio: 'Hello World' },
update: { bio: 'Hello World' },
},
},
},
});
通过更新现有 User 记录所连接的两个 Post 记录或创建新记录来更新现有 User 记录(upsert)
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
upsert: [
{
create: { title: 'This is my first post' },
update: { title: 'This is my first post' },
where: { id: 32 },
},
{
create: { title: 'This is my second post' },
update: { title: 'This is my second post' },
where: { id: 23 },
},
],
},
},
});
delete
嵌套的 delete 查询会删除相关记录。父记录不会被删除。
备注
delete仅在关系可选时可用。
示例
通过删除现有 User 记录所连接的 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
delete: true,
},
},
});
通过删除现有 User 记录所连接的两个 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
delete: [{ id: 34 }, { id: 36 }],
},
},
});
updateMany
嵌套的 updateMany 会更新相关记录列表并支持筛选——例如,您可以更新用户的未发布帖子。
示例
更新属于特定用户的所有未发布帖子
const result = await prisma.user.update({
where: {
id: 2,
},
data: {
posts: {
updateMany: {
where: {
published: false,
},
data: {
likes: 0,
},
},
},
},
});
deleteMany
嵌套的 deleteMany 会删除相关记录并支持筛选。例如,您可以在更新该用户的其他属性时删除该用户的帖子。
示例
作为更新的一部分,删除属于特定用户的所有帖子
const result = await prisma.user.update({
where: {
id: 2,
},
data: {
name: 'Updated name',
posts: {
deleteMany: {},
},
},
});
筛选条件和运算符
equals
值等于 n。
示例
返回所有 name 等于 "Eleanor" 的用户
const result = await prisma.user.findMany({
where: {
name: {
equals: 'Eleanor',
},
},
});
您也可以省略 equals
const result = await prisma.user.findMany({
where: {
name: 'Eleanor',
},
});
返回所有数量低于“警告数量”阈值的产品
此示例比较了同一模型的字段,该功能从版本 4.3.0 开始可用。
const productsWithLowQuantity = await prisma.product.findMany({
where: {
quantity: {
lte: prisma.product.fields.warnQuantity
},
},
});
返回所有收藏颜色为蓝色和绿色的用户
此示例查找将其 favoriteColors 字段设置为 ['blue', 'green'] 的用户。
请注意,当使用 equals 时,元素的顺序很重要。也就是说 ['blue', 'green'] 不等于 ['green', 'blue']
const favoriteColorFriends = await prisma.user.findMany({
where: {
favoriteColors: {
equals: ['blue', 'green'],
},
},
});
not
值不等于 n。
示例
返回所有 name 不等于 "Eleanor" 的用户
const result = await prisma.user.findMany({
where: {
name: {
not: 'Eleanor',
},
},
});
not 将返回所有不匹配给定值的项目。但是,如果列可为空,则不会返回 NULL 值。如果您需要返回 null 值,请使用 OR 运算符以包含 NULL 值。
返回所有 name 不等于 "Eleanor" 的用户,包括 name 为 NULL 的用户
await prisma.user.findMany({
where: {
OR: [
{ name: { not: 'Eleanor' } },
{ name: null }
]
}
})
in
值 n 存在于列表中。
null 值不会被返回。例如,如果您组合使用 in 和 NOT 来返回名称不在列表中的用户,则不会返回名称为 null 值的用户。
示例
获取 id 可以在以下列表中找到的 User 记录:[22, 91, 14, 2, 5]
const getUser = await prisma.user.findMany({
where: {
id: { in: [22, 91, 14, 2, 5] },
},
});
获取 name 可以在以下列表中找到的 User 记录:['Saqui', 'Clementine', 'Bob']
const getUser = await prisma.user.findMany({
where: {
name: { in: ['Saqui', 'Clementine', 'Bob'] },
},
});
获取 name 不在列表中的 User 记录
以下示例结合了 in 和 NOT。您也可以使用 notIn。
const getUser = await prisma.user.findMany({
where: {
NOT: {
name: { in: ['Saqui', 'Clementine', 'Bob'] },
},
},
});
获取至少一个 Post 包含至少一个指定 Category 的 User 记录
const getUser = await prisma.user.findMany({
where: {
// Find users where..
posts: {
some: {
// ..at least one (some) posts..
categories: {
some: {
// .. have at least one category ..
name: {
in: ['Food', 'Introductions'], // .. with a name that matches one of the following.
},
},
},
},
},
},
});
notIn
值 n 不存在于列表中。
备注
null值不会被返回。
示例
获取 id 不在以下列表中的 User 记录:[22, 91, 14, 2, 5]
const getUser = await prisma.user.findMany({
where: {
id: { notIn: [22, 91, 14, 2, 5] },
},
});
lt
值 n 小于 x。
示例
获取所有 likes 小于 9 的 Post 记录
const getPosts = await prisma.post.findMany({
where: {
likes: {
lt: 9,
},
},
});
lte
值 n 小于或等于 x。
示例
获取所有 likes 小于或等于 9 的 Post 记录
const getPosts = await prisma.post.findMany({
where: {
likes: {
lte: 9,
},
},
});
gt
值 n 大于 x。
示例
获取所有 likes 大于 9 的 Post 记录
const getPosts = await prisma.post.findMany({
where: {
likes: {
gt: 9,
},
},
});
gte
值 n 大于或等于 x。
示例
获取所有 likes 大于或等于 9 的 Post 记录
const getPosts = await prisma.post.findMany({
where: {
likes: {
gte: 9,
},
},
});
示例
获取所有 date_created 晚于 2020 年 3 月 19 日的 Post 记录
const result = await prisma.post.findMany({
where: {
date_created: {
gte: new Date('2020-03-19T14:21:00+0200') /* Includes time offset for UTC */,
},
},
});
contains
值 n 包含 x。
示例
统计所有 content 包含 databases 的 Post 记录
const result = await prisma.post.count({
where: {
content: {
contains: 'databases',
},
},
});
统计所有 content 不包含 databases 的 Post 记录
const result = await prisma.post.count({
where: {
NOT: {
content: {
contains: 'databases',
},
},
},
});
search
使用全文搜索在 String 字段中进行搜索。
对于 PostgreSQL,此功能仍处于预览阶段。要使用它,请启用 fullTextSearchPostgres 功能标志。
示例
查找所有标题包含 cat 或 dog 的帖子。
const result = await prisma.post.findMany({
where: {
title: {
search: 'cat | dog',
},
},
});
查找所有标题包含 cat 和 dog 的帖子。
const result = await prisma.post.findMany({
where: {
title: {
search: 'cat & dog',
},
},
});
查找所有标题不包含 cat 的帖子。
const result = await prisma.post.findMany({
where: {
title: {
search: '!cat',
},
},
});
mode
备注
- 仅 PostgreSQL 和 MongoDB 连接器支持
示例
获取所有 title 包含 prisma(不区分大小写)的 Post 记录
const result = await prisma.post.findMany({
where: {
title: {
contains: 'prisma',
mode: 'insensitive',
},
},
});
startsWith
示例
获取所有 title 以 Pr 开头(例如 Prisma)的 Post 记录
const result = await prisma.post.findMany({
where: {
title: {
startsWith: 'Pr',
},
},
});
endsWith
获取所有 email 以 prisma.io 结尾的 User 记录
const result = await prisma.user.findMany({
where: {
email: {
endsWith: 'prisma.io',
},
},
});
AND
所有条件必须返回 true。或者,将对象列表传递到 where 子句中——不需要 AND 运算符。
示例
获取所有 content 字段包含 Prisma 且 published 为 false 的 Post 记录
const result = await prisma.post.findMany({
where: {
AND: [
{
content: {
contains: 'Prisma',
},
},
{
published: {
equals: false,
},
},
],
},
});
获取所有 content 字段包含 Prisma 且 published 为 false 的 Post 记录(无 AND)
以下格式返回与上一个示例相同的结果,不带 AND 运算符
const result = await prisma.post.findMany({
where: {
content: {
contains: 'Prisma',
},
published: {
equals: false,
},
},
});
获取所有 title 字段包含 Prisma 或 databases 且 published 为 false 的 Post 记录
以下示例结合了 OR 和 AND
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
AND: {
published: false,
},
},
});
OR
一个或多个条件必须返回 true。
示例
获取所有 title 字段包含 Prisma 或 databases 的 Post 记录
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
},
});
获取所有 title 字段包含 Prisma 或 databases 但不包含 SQL 的 Post 记录
以下示例结合了 OR 和 NOT
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
NOT: {
title: {
contains: 'SQL',
},
},
},
});
获取所有 title 字段包含 Prisma 或 databases 且 published 为 false 的 Post 记录
以下示例结合了 OR 和 AND
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
AND: {
published: false,
},
},
});
NOT
所有条件必须返回 false。
示例
获取所有 title 不包含 SQL 的 Post 记录
const result = await prisma.post.findMany({
where: {
NOT: {
title: {
contains: 'SQL',
},
},
},
});
获取所有 title 字段包含 Prisma 或 databases 但不包含 SQL,并且相关 User 记录的电子邮件地址不包含 sarah 的 Post 记录
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
NOT: {
title: {
contains: 'SQL',
},
},
user: {
NOT: {
email: {
contains: 'sarah',
},
},
},
},
include: {
user: true,
},
});
关系筛选器
some
返回所有一个或多个(“some”)相关记录匹配筛选条件的记录。
备注
- 您可以在不带参数的情况下使用
some来返回所有至少有一个关系的记录
示例
获取所有 User 记录,其中一些帖子提到了 Prisma
const result = await prisma.user.findMany({
where: {
post: {
some: {
content: {
contains: "Prisma"
}
}
}
}
}
every
返回所有所有(“every”)相关记录匹配筛选条件的记录。
示例
获取所有 User 记录,其中所有帖子都已发布
const result = await prisma.user.findMany({
where: {
post: {
every: {
published: true
},
}
}
}
none
返回所有零相关记录匹配筛选条件的记录。
备注
- 您可以在不带参数的情况下使用
none来返回所有没有关系的记录
示例
获取所有零帖子的 User 记录
const result = await prisma.user.findMany({
where: {
post: {
none: {} // User has no posts
}
}
}
获取所有零已发布帖子的 User 记录
const result = await prisma.user.findMany({
where: {
post: {
none: {
published: true
}
}
}
}
is
返回所有相关记录匹配筛选条件的记录(例如,用户的名称 is Bob)。
示例
获取所有用户名为 "Bob" 的 Post 记录
const result = await prisma.post.findMany({
where: {
user: {
is: {
name: "Bob"
},
}
}
}
isNot
返回所有相关记录不匹配筛选条件的记录(例如,用户的名称 isNot Bob)。
示例
获取所有用户名不是 "Bob" 的 Post 记录
const result = await prisma.post.findMany({
where: {
user: {
isNot: {
name: "Bob"
},
}
}
}
标量列表方法
set
使用 set 覆盖标量列表字段的值。
备注
-
set是可选的——您可以直接设置值tags: ['computers', 'books'];
示例
将 tags 的值设置为字符串值列表
const setTags = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
set: ['computing', 'books'],
},
},
});
将 tags 设置为值列表,不使用 set 关键字
const setTags = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: ['computing', 'books'],
},
});
将 tags 的值设置为单个字符串值
const setTags = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
set: 'computing',
},
},
});
push
push 在版本 2.20.0 及更高版本中可用。使用 push 将一个值或多个值添加到标量列表字段中。
备注
- 仅适用于 PostgreSQL 和 MongoDB。
- 您可以推送一个值列表或单个值。
示例
向 tags 列表中添加一个 computing 项
const addTag = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
push: 'computing',
},
},
});
const addTag = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
push: ['computing', 'genetics'],
},
},
});
unset
此方法仅在 MongoDB 版本的 3.11.1 及更高版本中可用。
使用 unset 来取消设置标量列表的值。与 set: null 不同,unset 会完全删除该列表。
示例
取消设置 tags 的值
const setTags = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
unset: true,
},
},
});
标量列表筛选器
标量列表筛选器允许您按列表/数组字段的内容进行筛选。
备注
- 标量列表/数组筛选器忽略
NULL值。使用isEmpty或NOT不会返回具有NULL值列表/数组的记录,并且{ equals: null }会导致错误。
has
给定值存在于列表中。
示例
以下查询返回所有 tags 列表包含 "databases" 的 Post 记录
const posts = await client.post.findMany({
where: {
tags: {
has: 'databases',
},
},
});
以下查询返回所有 tags 列表不包含 "databases" 的 Post 记录
const posts = await client.post.findMany({
where: {
NOT: {
tags: {
has: 'databases',
},
},
},
});
hasEvery
列表中存在所有值。
示例
以下查询返回所有 tags 列表至少包含 "databases" 和 "typescript" 的 Post 记录
const posts = await prisma.post.findMany({
where: {
tags: {
hasEvery: ['databases', 'typescript'],
},
},
});
hasSome
列表中至少存在一个值。
示例
以下查询返回所有 tags 列表包含 "databases" 或 "typescript" 的 Post 记录
const posts = await prisma.post.findMany({
where: {
tags: {
hasSome: ['databases', 'typescript'],
},
},
});
isEmpty
列表为空。
示例
以下查询返回所有没有标签的 Post 记录
const posts = await prisma.post.findMany({
where: {
tags: {
isEmpty: true,
},
},
});
isSet
此筛选器仅在 MongoDB 版本的 3.11.1 及更高版本中可用。
筛选列表以仅包含已设置(设置为值或显式设置为 null)的结果。将此筛选器设置为 true 将排除根本未设置的未定义结果。
示例
以下查询返回所有 tags 已设置为 null 或值的 Post 记录
const posts = await prisma.post.findMany({
where: {
tags: {
isSet: true,
},
},
});
equals
列表精确匹配给定值。
示例
以下查询返回所有 tags 列表仅包含 "databases" 和 "typescript" 的 Post 记录
const posts = await prisma.post.findMany({
where: {
tags: {
equals: ['databases', 'typescript'],
},
},
});
复合类型方法
仅在 Prisma 3.10.0 及更高版本中适用于 MongoDB。
复合类型方法允许您创建、更新和删除复合类型。
set
使用 set 覆盖复合类型的值。
备注
set关键字是可选的——您可以直接设置值photos: [
{ height: 100, width: 200, url: '1.jpg' },
{ height: 100, width: 200, url: '2.jpg' },
];
示例
在新 order 中设置 shippingAddress 复合类型
const order = await prisma.order.create({
data: {
// Normal relation
product: { connect: { id: 'some-object-id' } },
color: 'Red',
size: 'Large',
// Composite type
shippingAddress: {
set: {
street: '1084 Candycane Lane',
city: 'Silverlake',
zip: '84323',
},
},
},
});
将可选复合类型设置为 null
const order = await prisma.order.create({
data: {
// Embedded optional type, set to null
billingAddress: {
set: null,
},
},
});
unset
使用 unset 来取消设置复合类型的值。与 set: null 不同,这会从 MongoDB 文档中完全删除该字段。
示例
从 order 中删除 billingAddress
const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
billingAddress: {
// Unset the billing address
// Removes "billingAddress" field from order
unset: true,
},
},
});
update
使用 update 更新必需复合类型中的字段。
备注
update 方法不能用于可选类型。请改用 upsert
示例
更新 shippingAddress 复合类型的邮政编码字段
const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
shippingAddress: {
// Update just the zip field
update: {
zip: '41232',
},
},
},
});
upsert
使用 upsert 更新现有可选复合类型(如果存在),否则设置复合类型。
备注
upsert 方法不能用于必需类型。请改用 update
示例
如果不存在,则创建新的 billingAddress,否则更新它
const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
billingAddress: {
// Create the address if it doesn't exist,
// otherwise update it
upsert: {
set: {
street: '1084 Candycane Lane',
city: 'Silverlake',
zip: '84323',
},
update: {
zip: '84323',
},
},
},
},
});
push
使用 push 将值推送到复合类型列表的末尾。
示例
将新照片添加到 photos 列表
const product = prisma.product.update({
where: {
id: 10,
},
data: {
photos: {
// Push a photo to the end of the photos list
push: [{ height: 100, width: 200, url: '1.jpg' }],
},
},
});
复合类型筛选器
仅在 Prisma 3.11.0 及更高版本中适用于 MongoDB。
复合类型筛选器允许您筛选复合类型的内容。
equals
使用 equals 通过匹配复合类型或复合类型列表来筛选结果。要求复合类型的所有必需字段都匹配。
备注
当匹配可选字段时,您需要区分文档中未定义的(缺失的)字段和已显式设置为 null 的字段
- 如果您省略可选字段,它将匹配未定义的字段,但不会匹配已设置为
null的字段 - 如果您使用
equals: { ... exampleField: null ... }筛选可选字段的null值,那么它将仅匹配该字段已设置为null的文档,而不匹配未定义的字段
使用 equals 时,字段和列表的顺序很重要
- 对于字段,
{ "a": "1", "b": "2" }和{ "b": "2", "a": "1" }不被视为相等 - 对于列表,
[ { "a": 1 }, { "a": 2 } ]和[ { "a": 2 }, { "a": 1 } ]不被视为相等
示例
查找与给定 shippingAddress 完全匹配的订单
const orders = await prisma.order.findMany({
where: {
shippingAddress: {
equals: {
street: '555 Candy Cane Lane',
city: 'Wonderland',
zip: '52337',
},
},
},
});
查找照片与所有给定 url 列表匹配的产品
const product = prisma.product.findMany({
where: {
equals: {
photos: [{ url: '1.jpg' }, { url: '2.jpg' }],
},
},
});
is
使用 is 通过匹配复合类型中的特定字段来筛选结果。
示例
查找 shippingAddress 匹配给定街道名称的订单
const orders = await prisma.order.findMany({
where: {
shippingAddress: {
is: {
street: '555 Candy Cane Lane',
},
},
},
});
isNot
使用 isNot 筛选复合类型字段不匹配的结果。
示例
查找 shippingAddress 不匹配给定邮政编码的订单
const orders = await prisma.order.findMany({
where: {
shippingAddress: {
isNot: {
zip: '52337',
},
},
},
});
isEmpty
使用 isEmpty 筛选复合类型的空列表结果。
示例
查找没有照片的产品
const product = prisma.product.findMany({
where: {
photos: {
isEmpty: true,
},
},
});
every
使用 every 筛选复合类型列表,其中列表中的每个项目都匹配条件
示例
查找第一款所有照片高度都为 200 的产品
const product = await prisma.product.findFirst({
where: {
photos: {
every: {
height: 200,
}
}
},
})
some
使用 some 筛选复合类型列表,其中列表中一个或多个项目匹配条件。
示例
查找第一款一个或多个照片 url 为 2.jpg 的产品
const product = await prisma.product.findFirst({
where: {
photos: {
some: {
url: "2.jpg",
}
}
},
})
none
使用 none 筛选复合类型列表,其中列表中没有项目匹配条件。
示例
查找第一款没有照片 url 为 2.jpg 的产品
const product = await prisma.product.findFirst({
where: {
photos: {
none: {
url: "2.jpg",
}
}
},
})
原子数字运算
更新时的原子操作适用于数字字段类型(Float 和 Int)。此功能允许您根据字段的当前值(例如减去或除以)更新字段,而不会冒竞态条件的风险。
概述:竞态条件
当需要按顺序完成两个或更多操作才能完成任务时,就会发生竞态条件。在以下示例中,两个客户端尝试将同一字段(postCount)增加一
| 客户端 | 操作 | 值 |
|---|---|---|
| 客户端 1 | 获取字段值 | 21 |
| 客户端 2 | 获取字段值 | 21 |
| 客户端 2 | 设置字段值 | 22 |
| 客户端 1 | 设置字段值 | 22 ✘ |
值应该是 23,但两个客户端没有按顺序读写 postCount 字段。更新时的原子操作将读写组合成一个操作,从而防止竞态条件
| 客户端 | 操作 | 值 |
|---|---|---|
| 客户端 1 | 获取并设置字段值 | 21 → 22 |
| 客户端 2 | 获取并设置字段值 | 22 → 23 ✔ |
运算符
| 选项 | 描述 |
|---|---|
increment | 将 n 添加到当前值。 |
decrement | 从当前值中减去 n。 |
multiply | 将当前值乘以 n。 |
divide | 将当前值除以 n。 |
set | 设置当前字段值。与 { myField : n } 相同。 |
备注
- 每次查询,每个字段只能执行一个原子更新。
- 如果字段为
null,它不会被increment、decrement、multiply或divide更新。
示例
将所有 Post 记录的所有 view 和 likes 字段增加 1
const updatePosts = await prisma.post.updateMany({
data: {
views: {
increment: 1,
},
likes: {
increment: 1,
},
},
});
将所有 Post 记录的所有 views 字段设置为 0
const updatePosts = await prisma.post.updateMany({
data: {
views: {
set: 0,
},
},
});
也可以写成
const updatePosts = await prisma.post.updateMany({
data: {
views: 0,
},
});
Json 筛选器
有关用例和高级示例,请参阅:使用 Json 字段。
由PostgreSQL和MySQL支持,path 选项的语法不同。PostgreSQL 不支持筛选数组中的对象键值。
本节中的示例假定 pet 字段的值是
{
"favorites": {
"catBreed": "Turkish van",
"dogBreed": "Rottweiler",
"sanctuaries": ["RSPCA", "Alley Cat Allies"],
"treats": [
{ "name": "Dreamies", "manufacturer": "Mars Inc" },
{ "name": "Treatos", "manufacturer": "The Dog People" }
]
},
"fostered": {
"cats": ["Bob", "Alice", "Svetlana the Magnificent", "Queenie"]
},
"owned": {
"cats": ["Elliott"]
}
}
备注
Json筛选器的实现在不同数据库连接器之间有所不同- PostgreSQL 中的筛选器区分大小写,并且尚不支持
mode
path
path 表示特定键的位置。以下查询返回所有嵌套 favourites > dogBreed 键等于 "Rottweiler" 的用户。
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'dogBreed'],
equals: 'Rottweiler',
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.favorites.dogBreed',
equals: 'Rottweiler',
},
},
});
以下查询返回所有嵌套 owned > cats 数组包含 "Elliott" 的用户。
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['owned', 'cats'],
array_contains: ['Elliott'],
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.owned.cats',
array_contains: 'Elliott',
},
},
});
筛选数组内部对象的键值(如下)仅由 MySQL 连接器支持。
以下查询返回所有嵌套 favorites > treats 数组包含 name 值为 "Dreamies" 的对象的用户
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.favorites.treats[*].name',
array_contains: 'Dreamies',
},
},
});
string_contains
以下查询返回所有嵌套 favorites > catBreed 键值包含 "Van" 的用户
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'catBreed'],
string_contains: 'Van',
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.favorites.catBreed',
string_contains: 'Van',
},
},
});
string_starts_with
以下查询返回所有嵌套 favorites > catBreed 键值以 "Turkish" 开头的用户
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'catBreed'],
string_starts_with: 'Turkish',
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.favorites.catBreed',
string_starts_with: 'Turkish',
},
},
});
string_ends_with
以下查询返回所有嵌套 favorites > catBreed 键值以 "Van" 结尾的用户
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'catBreed'],
string_ends_with: 'Van',
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.favorites.catBreed',
string_ends_with: 'Van',
},
},
});
mode
指定字符串筛选是否应区分大小写(默认)或不区分大小写。
以下查询返回所有嵌套 favorites > catBreed 键值包含 "Van" 或 "van" 的用户
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'catBreed'],
string_contains: 'Van',
mode: "insensitive",
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.favorites.catBreed',
string_contains: 'Van',
mode: "insensitive",
},
},
});
array_contains
以下查询返回所有 sanctuaries 数组包含值 "RSPCA" 的用户
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['sanctuaries'],
array_contains: ['RSPCA'],
},
},
});
注意:在 PostgreSQL 中,array_contains 的值必须是一个数组而不是字符串,即使数组只包含一个值。
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.sanctuaries',
array_contains: 'RSPCA',
},
},
});
以下查询返回所有 sanctuaries 数组包含给定数组中所有值的用户
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['sanctuaries'],
array_contains: ['RSPCA', 'Alley Cat Allies'],
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.sanctuaries',
array_contains: ['RSPCA', 'Alley Cat Allies'],
},
},
});
array_starts_with
以下查询返回所有 sanctuaries 数组以值 "RSPCA" 开头的用户
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['sanctuaries'],
array_starts_with: 'RSPCA',
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.sanctuaries',
array_starts_with: 'RSPCA',
},
},
});
array_ends_with
以下查询返回所有 sanctuaries 数组以值 "Alley Cat Allies" 结尾的用户
- PostgreSQL
- MySQL
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['sanctuaries'],
array_ends_with: 'Alley Cat Allies',
},
},
});
const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.sanctuaries',
array_ends_with: 'Alley Cat Allies',
},
},
});
客户端方法
注意:客户端级别的方法前缀为 $。
备注
$on和$use客户端方法在通过$extends扩展的客户端实例上不存在
$disconnect()
$disconnect() 方法关闭调用 $connect 时建立的数据库连接,并停止运行 Prisma ORM 查询引擎的进程。有关 $connect() 和 $disconnect() 的概述,请参阅连接管理。
备注
$disconnect()返回一个Promise,因此您应该在带有await关键字的async函数中调用它。
$connect()
$connect() 方法通过 Prisma ORM 的查询引擎建立与数据库的物理连接。有关 $connect() 和 $disconnect() 的概述,请参阅连接管理。
备注
$connect()返回一个Promise,因此您应该在带有await关键字的async函数中调用它。
$on()
$on 在扩展客户端中不可用。请迁移到客户端扩展或在扩展客户端之前使用 $on 方法。
$use()
$use() 方法添加中间件
prisma.$use(async (params, next) => {
console.log('This is middleware!');
// Modify or interrogate params here
return next(params);
});
next
next 表示中间件堆栈中的“下一层”,根据您在堆栈中的位置,它可能是下一个中间件或 Prisma 查询。
params
params 是一个包含用于中间件信息的对象。
| 参数 | 描述 |
|---|---|
action | 查询类型——例如,create 或 findMany。 |
args | 传递给查询的参数——例如,where、data 或 orderBy |
dataPath | 如果您使用流畅 API,则会填充此项。 |
model | 模型类型——例如,Post 或 User。 |
runInTransaction | 如果查询在事务上下文中运行,则返回 true。 |
如果您需要 model 属性作为字符串,请使用:String(params.model)
示例参数值
{
args: { where: { id: 15 } },
dataPath: [ 'select', 'author', 'select', 'posts' ],
runInTransaction: false,
action: 'findMany',
model: 'Post'
}
示例
请参阅中间件示例。
$queryRawTyped
请参阅:使用原始 SQL ($queryRawTyped)。
$queryRaw
请参阅:使用原始 SQL ($queryRaw)。
$queryRawUnsafe()
请参阅:使用原始 SQL ($queryRawUnsafe())。
$executeRaw
$executeRawUnsafe()
请参阅:使用原始 SQL ($executeRawUnsafe())。
$runCommandRaw()
请参阅:使用原始 SQL ($runCommandRaw())。
$transaction()
请参阅:事务。
$metrics
Prisma Client 指标为您提供了 Prisma Client 如何与数据库交互的详细见解。您可以使用此见解来帮助诊断应用程序的性能问题。了解更多:指标。
Prisma Client 指标具有以下方法
$metrics.json():以 JSON 格式检索 Prisma Client 指标。$metrics.prometheus():以 Prometheus 格式检索 Prisma Client 指标。
$extends
使用 $extends,您可以创建和使用 Prisma Client 扩展,以以下方式向 Prisma Client 添加功能
model:向您的模型添加自定义方法client:向您的客户端添加自定义方法query:创建自定义 Prisma Client 查询result:向您的查询结果添加自定义字段
了解更多:Prisma Client 扩展。
实用类型
实用类型是 Prisma 命名空间中的辅助函数和类型。它们对于保持应用程序类型安全很有用。
Prisma.validator
validator 帮助您基于架构模型创建可重用的查询参数,同时确保您创建的对象是有效的。另请参阅:使用 Prisma.validator
您可以通过两种方式使用 validator
使用生成的 Prisma Client 类型
使用类型提供了一种类型级别的方法来验证数据
Prisma.validator<GeneratedType>({ args });
使用“选择器”
使用选择器模式时,您可以使用现有 Prisma Client 实例来创建验证器。此模式允许您选择要验证的模型、操作和查询选项。
您还可以使用已通过Prisma Client 扩展进行扩展的 Prisma Client 实例。
Prisma.validator(PrismaClientInstance, '<model>', '<operation>', '<query option>')({ args });
示例
以下示例展示了如何在应用中提取和验证可重用的 create 操作的输入
import { Prisma } from '@prisma/client';
const validateUserAndPostInput = (name, email, postTitle) => {
return Prisma.validator<Prisma.UserCreateInput>()({
name,
email,
posts: {
create: {
title: postTitle,
},
},
});
};
这是同一操作的另一种语法
import { Prisma } from '@prisma/client';
import prisma from './prisma';
const validateUserAndPostInput = (name, email, postTitle) => {
return Prisma.validator(
prisma,
'user',
'create',
'data'
)({
name,
email,
posts: {
create: {
title: postTitle,
},
},
});
};
比较同一表中的列
您可以直接比较同一表中的列,适用于非唯一过滤器。
此功能在 5.0.0 版本中已普遍可用,并从 Prisma ORM 4.3.0 到 4.16.2 版本通过 fieldReference 预览功能提供。
在以下情况下,您必须使用原始查询来比较同一表中的列
- 如果您的版本早于 4.3.0
- 如果您想使用唯一过滤器,例如
findUnique或findUniqueOrThrow - 如果您想将字段与唯一约束进行比较
- 如果您想使用以下运算符之一,在 MySQL 或 MariaDB 中将JSON 字段与另一个字段进行比较:
gt、gte、lt或lte。请注意,您可以使用这些运算符将 JSON 字段与标量值进行比较。此限制仅适用于您尝试将 JSON 字段与另一个字段进行比较的情况。
要比较同一表中的列,请使用 <model>.fields 属性。在以下示例中,查询返回 prisma.product.quantity 字段中的值小于或等于 prisma.product.warnQuantity 字段中的值的所有记录。
prisma.product.findMany({
where: { quantity: { lte: prisma.product.fields.warnQuantity } },
});
fields 是每个模型的特殊属性。它包含该模型的字段列表。
注意事项
字段必须是同一类型
您只能对同一类型的字段进行比较。例如,以下情况会引发错误
await prisma.order.findMany({
where: {
id: { equals: prisma.order.fields.due },
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Type error: id is a string, while amountDue is an integer
},
});
字段必须在同一模型中
您只能使用 fields 属性对同一模型中的字段进行比较。以下示例不起作用
await prisma.order.findMany({
where: {
id: { equals: prisma.user.fields.name },
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Type error: name is a field on the User model, not Order
},
});
但是,您可以使用标准查询比较不同模型中的字段。
在 groupBy 模型查询中,将引用的字段放入 by 参数中
如果您使用带有 having 选项的 groupBy 模型查询,则必须将引用的字段放入 by 参数中。
以下示例有效
prisma.user.groupBy({
by: ['id', 'name'],
having: { id: { equals: prisma.user.fields.name } },
});
以下示例无效,因为 name 不在 by 参数中
prisma.user.groupBy({
by: ['id'],
having: { id: { equals: prisma.user.fields.name } },
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// name is not in the 'by' argument
});
在标量列表中搜索字段
如果您的数据源支持标量列表(例如在 PostgreSQL 中),则可以搜索特定字段位于字段列表中的所有记录。为此,请使用 in 和 notIn 过滤器引用标量列表。例如
await prisma.user.findMany({
where: {
// find all users where 'name' is in a list of tags
name: { in: prisma.user.fields.tags },
},
});
使用 UserWhereUniqueInput 筛选非唯一字段
从 5.0.0 版本开始,where 上生成的类型 UserWhereUniqueInput 会公开模型上的所有字段,而不仅仅是唯一字段。此功能在 4.5.0 到 4.16.2 版本之间,通过 extendedWhereUnique 预览标志提供
您必须在 where 语句中在布尔运算符之外指定至少一个唯一字段,并且可以指定任意数量的附加唯一和非唯一字段。您可以使用此功能向返回单个记录的任何操作添加过滤器。例如,您可以将此功能用于以下情况
从 4.6.0 版本开始,您可以使用此功能筛选可选的一对一嵌套读取。
更新的乐观并发控制
您可以筛选非唯一字段以在 update 操作上执行乐观并发控制。
要执行乐观并发控制,我们建议您使用 version 字段来检查记录或相关记录中的数据在代码执行期间是否已更改。在 4.5.0 版本之前,您无法在 update 操作中评估 version 字段,因为该字段是非唯一的。从 4.5.0 版本开始,您可以评估 version 字段。
在以下示例中,updateOne 和 updateTwo 首先读取同一条记录,然后尝试更新它。数据库仅在 version 中的值与初始读取时的值相同时才执行这些更新。当数据库执行这些更新中的第一个(可能是 updateOne 或 updateTwo,取决于时序)时,它会递增 version 中的值。这意味着数据库不会执行第二个更新,因为 version 中的值已更改。
model User {
id Int @id @default(autoincrement())
email String @unique
city String
version Int
}
function updateOne() {
const user = await prisma.user.findUnique({ id: 1 });
await prisma.user.update({
where: { id: user.id, version: user.version },
data: { city: 'Berlin', version: { increment: 1 } },
});
}
function updateTwo() {
const user = await prisma.user.findUnique({ id: 1 });
await prisma.user.update({
where: { id: user.id, version: user.version },
data: { city: 'New York', version: { increment: 1 } },
});
}
function main() {
await Promise.allSettled([updateOne(), updateTwo()]);
}
权限检查
您可以在更新期间筛选非唯一字段以检查权限。
在以下示例中,用户想要更新帖子标题。where 语句检查 authorId 中的值以确认用户是该帖子的作者。只有当用户是帖子作者时,应用程序才会更新帖子标题。
await prisma.post.update({
where: { id: 1, authorId: 1 },
data: { title: 'Updated post title' },
});
软删除
您可以筛选非唯一字段以处理软删除。
在以下示例中,如果帖子被软删除,我们不希望返回该帖子。该操作仅在 isDeleted 中的值为 false 时才返回帖子。
prisma.Post.findUnique({ where: { id: postId, isDeleted: false } });
UserWhereUniqueInput 注意事项
与 UserWhereUniqueInput 配合使用的布尔运算符
对于 UserWhereUniqueInput,您必须在布尔运算符 AND、OR、NOT 之外指定至少一个唯一字段。您仍然可以将这些布尔运算符与过滤器中的任何其他唯一字段或非唯一字段结合使用。
在以下示例中,我们将 id(一个唯一字段)与 email 结合测试。这是有效的。
await prisma.user.update({
where: { id: 1, OR: [{ email: "bob@prisma.io" }, { email: "alice@prisma.io" }] },
// ^^^ Valid: the expression specifies a unique field (`id`) outside of any boolean operators
data: { ... }
})
// SQL equivalent:
// WHERE id = 1 AND (email = "bob@prisma.io" OR email = "alice@prisma.io")
以下示例无效,因为没有任何布尔运算符之外的唯一字段
await prisma.user.update({
where: { OR: [{ email: "bob@prisma.io" }, { email: "alice@prisma.io" }] },
// ^^^ Invalid: the expressions does not contain a unique field outside of boolean operators
data: { ... }
})
一对一关系
从 4.5.0 版本开始,您可以在一对一关系的以下操作中筛选非唯一字段
- 嵌套更新
- 嵌套插入或更新 (upsert)
- 嵌套断开连接
- 嵌套删除
Prisma Client 会自动使用唯一过滤器来选择适当的相关记录。因此,您不需要在 where 语句中通过 WhereUniqueInput 生成的类型指定唯一过滤器。相反,where 语句具有 WhereInput 生成的类型。您可以使用此类型进行过滤,而不受 WhereUniqueInput 的限制。
嵌套更新示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
// Before Prisma version 4.5.0
update: { field: "updated" }
// From Prisma version 4.5.0, you can also do the following:
update: { where: { /*WhereInput*/ }, data: { field: "updated" } } }
}
}
})
嵌套插入或更新 (upsert) 示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
upsert: {
where: { /* WhereInput */ } // new argument from Prisma 4.5.0
create: { /* CreateInput */ },
update: { /* CreateInput */ },
}
}
}
})
嵌套断开连接示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
// Before Prisma version 4.5.0
disconnect: true
// From Prisma version 4.5.0, you can also do the following:
disconnect: { /* WhereInput */ }
}
}
})
嵌套删除示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
// Before Prisma version 4.5.0
delete: true
// From Prisma version 4.5.0, you can also do the following:
delete: { /* WhereInput */ }
}
}
})
PrismaPromise 行为
所有 Prisma Client 查询都返回 PrismaPromise 的实例。这是一个“thenable”,这意味着 PrismaPromise 仅在您调用 await 或 .then() 或 .catch() 时才执行。此行为与常规 JavaScript Promise 不同,后者会立即开始执行。
例如
const findPostOperation = prisma.post.findMany({}); // Query not yet executed
findPostOperation.then(); // Prisma Client now executes the query
// or
await findPostOperation; // Prisma Client now executes the query
使用 $transaction API 时,此行为使 Prisma Client 能够将所有查询作为一个事务传递给查询引擎。