Prisma Client API 参考
Prisma Client API 参考文档基于以下模式
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。数据源名称包含在生成的客户端中。
- 如果您在模式中将
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" }] |
日志级别
名称 | 示例 |
---|---|
query | 记录 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”, ], }, }) |
info | 示例prisma:info 在 http://127.0.0.1:58471 上启动了 http 服务器 |
warn | 警告。 |
error | 错误。 |
发射格式
名称 | 描述 |
---|---|
stdout | 参见:stdout |
event | 引发您可以订阅的事件。 |
事件类型
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 返回的错误的级别和格式。
错误格式
名称 | 描述 |
---|---|
undefined | 如果未定义,则默认为无色。 |
pretty | 启用漂亮的错误格式。 |
colorless (默认) | 启用无色错误格式。 |
minimal | 启用最小的错误格式。 |
示例
无错误格式
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 { Pool, neonConfig } from '@neondatabase/serverless';
import { PrismaNeon } from '@prisma/adapter-neon';
import { PrismaClient } from '@prisma/client';
import dotenv from 'dotenv';
import ws from 'ws';
dotenv.config();
neonConfig.webSocketConstructor = ws;
const connectionString = `${process.env.DATABASE_URL}`;
const pool = new Pool({ connectionString });
const adapter = new PrismaNeon(pool);
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
。
选项
选项 | 描述 |
---|---|
RejectOnNotFound | 全局启用(true / false )或抛出自定义错误。 |
RejectPerOperation | 每个操作启用(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 中引入的。
允许在构造函数级别全局设置事务选项。
备注
- 可以在每个事务级别覆盖事务级别。
选项
选项 | 描述 |
---|---|
maxWait | Prisma Client 获取数据库事务的最大等待时间。默认值为 2 秒。 |
timeout | 交互式事务在被取消并回滚之前可以运行的最大时间。默认值为 5 秒。 |
isolationLevel | 设置事务隔离级别。默认情况下,此值设置为当前数据库中配置的值。可用值可能因您使用的数据库而异。 |
示例
const prisma = new PrismaClient({
transactionOptions: {
isolationLevel: Prisma.TransactionIsolationLevel.Serializable,
maxWait: 5000, // default: 2000
timeout: 10000, // default: 5000
},
});
模型查询
使用模型查询对模型执行 CRUD 操作。另请参阅:CRUD
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 起处于预览阶段。 |
relationLoadStrategy | 'join' 或'query' | 否 | 默认值:join 。指定关系查询的加载策略。仅在与include (或关系字段上的select )结合使用时可用。自 5.9.0 起处于预览阶段。 |
返回类型
返回类型 | 示例 | 描述 |
---|---|---|
JavaScript 对象(类型化) | User | |
JavaScript 对象(普通) | { title: "Hello world" } | 使用select 和include 确定要返回的字段。 |
null | null | 未找到记录 |
示例
获取id
为42
的User
记录
const result = await prisma.user.findUnique({
where: {
id: 42,
},
});
获取email
为[email protected]
的User
记录
const result = await prisma.user.findUnique({
where: {
email: '[email protected]',
},
});
获取firstName
为Alice
且lastName
为Smith
的User
记录(@@unique
)
展开示例 User 模型,其中包含 @@unique 块
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
)
展开示例 User 模型,其中包含 @@id 块
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
。 -
它与
$transaction
API中的顺序操作不兼容。如果查询抛出PrismaClientKnownRequestError
,则 API 不会回滚调用数组中的任何操作。作为解决方法,您可以使用$transaction
API 的交互式事务,如下所示$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 起处于预览阶段。 |
relationLoadStrategy | 'join' 或'query' | 否 | 默认值:join 。指定关系查询的加载策略。仅在与include (或关系字段上的select )结合使用时可用。自 5.9.0 起处于预览阶段。 |
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性过滤列表。 |
orderBy | XOR<Enumerable<UserOrderByInput>, UserOrderByInput> | 否 | 允许您按任何属性对返回的列表进行排序。 |
返回类型
返回类型 | 示例 | 描述 |
---|---|---|
JavaScript 对象(类型化) | User | 指定要包含在返回对象中的属性。 |
JavaScript 对象(普通) | { title: "Hello world" } | 使用select 和include 确定要返回的字段。 |
null | null | 未找到记录 |
备注
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
。 -
它与
$transaction
API中的顺序操作不兼容。如果查询返回PrismaClientKnownRequestError
,则 API 不会回滚调用数组中的任何操作。作为解决方法,您可以使用$transaction
API 的交互式事务,如下所示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 起处于预览阶段。 |
relationLoadStrategy | 'join' 或'query' | 否 | 默认值:join 。指定关系查询的加载策略。仅在与include (或关系字段上的select )结合使用时可用。自 5.9.0 起处于预览阶段。 |
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性过滤列表。 |
orderBy | XOR<Enumerable<PostOrder ByInput>, PostOrderByInput> | 否 | 允许您按任何属性对返回的列表进行排序。 |
cursor
| UserWhereUniqueInput | 否 | 指定列表的位置(该值通常指定一个id 或其他唯一值)。 |
获取 | 数量 | 否 | 指定列表中应返回多少个对象(从开头(正值)或结尾(负值)或者如果已提及,则从cursor 位置开始查看)。 |
跳过 | 数量 | 否 | 指定应跳过列表中返回对象的多少个。 |
唯一 | 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
创建一个新的数据库记录。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
数据 | XOR<UserCreateInput, UserUncheckedCreateInput> | 是 | 将所有模型字段包装在一个类型中,以便在创建新记录时可以提供这些字段。它还包括关系字段,允许您执行(事务性)嵌套插入。在数据模型中标记为可选或具有默认值的字段是可选的。 |
select | XOR<UserSelect, null> | 否 | 指定要包含在返回对象中的属性。 |
include | XOR<UserInclude, null> | 否 | 指定应在返回对象上急切加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 起处于预览阶段。 |
relationLoadStrategy | '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: '[email protected]' },
});
创建多个新记录
在大多数情况下,您可以使用createMany()
或createManyAndReturn()
查询执行批量插入。但是,在某些情况下,create()
是插入多条记录的最佳选择。
以下示例将导致两个INSERT
语句
import { Prisma, PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({ log: ['query'] });
async function main() {
let users: Prisma.UserCreateInput[] = [
{
email: '[email protected]',
name: 'Ari',
profileViews: 20,
coinflips: [true, false, false],
role: 'ADMIN',
},
{
email: '[email protected]',
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
更新现有的数据库记录。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
数据 | XOR<UserUpdateInput UserUncheckedUpdateInput> | 是 | 包装模型的所有字段,以便在更新现有记录时可以提供这些字段。在数据模型中标记为可选或具有默认值的字段是可选的。 |
where | UserWhereUniqueInput | 是 | 包装模型的所有字段,以便可以选择记录(了解更多)。 在 4.5.0 版本之前,此类型仅包装模型的唯一字段。 |
select | XOR<UserSelect, null> | 否 | 指定要包含在返回对象中的属性。 |
include | XOR<UserInclude, null> | 否 | 指定应在返回对象上急切加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 起处于预览阶段。 |
relationLoadStrategy | 'join' 或'query' | 否 | 默认值:join 。指定关系查询的加载策略。仅在与include (或关系字段上的select )结合使用时可用。自 5.9.0 起处于预览阶段。 |
返回类型
返回类型 | 示例 | 描述 |
---|---|---|
JavaScript 对象(类型化) | User | |
JavaScript 对象(普通) | { name: "Alice Wonderland" } | 使用select 和include 确定要返回的字段。 |
RecordNotFound 异常 | 如果记录不存在,则抛出异常。 |
备注
示例
将id
为1
的User
记录的email
更新为[email protected]
const user = await prisma.user.update({
where: { id: 1 },
data: { email: '[email protected]' },
});
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 起处于预览阶段。 |
relationLoadStrategy | 'join' 或'query' | 否 | 默认值:join 。指定关系查询的加载策略。仅在与include (或关系字段上的select )结合使用时可用。自 5.9.0 起处于预览阶段。 |
返回类型
返回类型 | 示例 | 描述 |
---|---|---|
JavaScript 对象(类型化) | User | |
JavaScript 对象(普通) | { name: "Alice Wonderland" } | 使用select 和include 确定要返回的字段。 |
备注
- 要对更新执行算术运算(加、减、乘、除),请使用原子更新以防止竞争条件。
- 如果两个或多个 upsert 操作同时发生并且记录尚不存在,则可能会发生竞争条件。结果,一个或多个 upsert 操作可能会抛出唯一键约束错误。您的应用程序代码可以捕获此错误并重试操作。了解更多。
- 从 4.6.0 版本开始,Prisma ORM 在可能的情况下将 upsert 查询交给数据库处理。了解更多。
示例
更新(如果存在)或创建一个新的email
为[email protected]
的User
记录
const user = await prisma.user.upsert({
where: { id: 1 },
update: { email: '[email protected]' },
create: { email: '[email protected]' },
});
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 查询条件
当查询满足以下条件时,Prisma Client 会对upsert
查询使用数据库 upsert
upsert
的create
和update
选项中没有嵌套查询- 查询不包含使用嵌套读取的选择
- 查询仅修改一个模型
upsert
的where
选项中只有一个唯一字段where
选项中的唯一字段和create
选项中的唯一字段具有相同的值
如果您的查询不满足这些条件,则 Prisma Client 会自行处理 upsert。
数据库 upsert 示例
以下示例使用此模式
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: '[email protected]',
},
update: {
email: '[email protected]',
},
});
在这种情况下,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: '[email protected]',
},
update: {
email: '[email protected]',
},
});
在以下查询中,where
和 create
选项中 userName
的值不同,因此 Prisma Client 不使用数据库 upsert。
prisma.User.upsert({
where: {
userName: 'Alice',
},
create: {
id: 1,
profileViews: 1,
userName: 'AliceS',
email: '[email protected]',
},
update: {
email: '[email protected]',
},
});
在以下查询中,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: '[email protected]',
},
update: {
email: '[email protected]',
},
});
delete()
delete
删除现有的数据库记录。您可以删除记录
- 通过ID
- 通过唯一属性
要删除与特定条件匹配的记录,请使用带过滤器的 deleteMany
。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
where | UserWhereUniqueInput | 是 | 包装模型的所有字段,以便可以选择记录(了解更多)。 在 4.5.0 版本之前,此类型仅包装模型的唯一字段。 |
select | XOR<UserSelect, null> | 否 | 指定要包含在返回对象中的属性。 |
include | XOR<UserInclude, null> | 否 | 指定应在返回对象上急切加载的关系。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 起处于预览阶段。 |
relationLoadStrategy | '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
等于 [email protected]
的 User
记录
以下查询删除特定用户记录并使用 select
返回已删除用户的 name
和 email
const deleteUser = await prisma.user.delete({
where: {
email: '[email protected]',
},
select: {
email: true,
name: true,
},
});
{ "email": "[email protected]", "name": "Elsa" }
createMany()
createMany
在事务中创建多条记录。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
数据 | Enumerable<UserCreateManyInput> | 是 | 将所有模型字段包装在一个类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
skipDuplicates? | boolean | 否 | 不要插入具有唯一字段或已存在 ID 字段的记录。仅受支持数据库支持 ON CONFLICT DO NOTHING 。这排除了 MongoDB 和 SQLServer |
返回类型
返回类型 | 示例 | 描述 |
---|---|---|
BatchPayload | { count: 3 } | 已创建记录的数量。 |
备注
- 从 Prisma ORM 5.12.0 版本开始,SQLite 现在支持
createMany()
。 - MongoDB、SQLServer 或 SQLite 不支持
skipDuplicates
选项。 - 您不能使用嵌套的
create
、createMany
、connect
、connectOrCreate
查询在顶级createMany()
查询中创建或连接关系。 - 您可以在
update()
或create()
查询中使用嵌套的createMany
查询 - 例如,同时添加一个User
和两个Post
记录,并使用嵌套的createMany
。
示例
创建几个新用户
const users = await prisma.user.createMany({
data: [
{ name: 'Sonali', email: '[email protected]' },
{ name: 'Alex', email: '[email protected]' },
],
});
createManyAndReturn()
createManyAndReturn
创建多个记录并返回结果对象。
createManyAndReturn()
仅在 Prisma ORM 5.14.0 及更高版本中可用。createManyAndReturn()
仅适用于 PostgreSQL、CockroachDB 和 SQLite。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
数据 | Enumerable<UserCreateManyInput> | 是 | 将所有模型字段包装在一个类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
select | XOR<UserSelect, null> | 否 | 指定要包含在返回对象中的属性。 |
omit | XOR<UserOmit, null> | 否 | 指定要从返回对象中排除的属性。自 5.13.0 版本起处于 预览 状态。与 select 互斥。 |
include | XOR<UserInclude, null> | 否 | 指定应在返回对象上急切加载哪些关系。 |
skipDuplicates? | boolean | 否 | 不要插入具有唯一字段或已存在 ID 字段的记录。仅受支持数据库支持 ON CONFLICT DO NOTHING 。这排除了 MongoDB 和 SQLServer |
备注
- SQLite 不支持
skipDuplicates
选项。 - 您不能使用嵌套的
create
、createMany
、connect
、connectOrCreate
查询在顶级createManyAndReturn()
查询中创建或连接关系。 - 当通过
include
包含关系时,每个关系都会生成一个单独的查询。 - 不支持
relationLoadStrategy: join
。
返回类型
返回类型 | 示例 | 描述 |
---|---|---|
JavaScript 数组对象(类型化) | User[] | |
JavaScript 数组对象(普通) | [{ name: "Sonali" }] | 使用 select 、omit 和 include 确定要返回的字段。 |
示例
创建并返回几个新用户
const users = await prisma.user.createManyAndReturn({
data: [
{ name: 'Sonali', email: '[email protected]' },
{ name: 'Alex', email: '[email protected]' },
],
})
[
{ "id": 0, "name": "Sonali", "email": "[email protected]", "profileViews": 0 },
{ "id": 1, "name": "Alex", "email": "[email protected]", "profileViews": 0 }
]
updateMany()
updateMany
批量更新一批现有的数据库记录并返回更新的记录数。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
数据 | 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',
},
});
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' },
});
有关如何过滤要删除的记录的示例,请参阅 过滤器条件和运算符。
count()
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性过滤列表。 |
orderBy | XOR<Enumerable<PostOrder ByInput>, PostOrderByInput> | 否 | 允许您按任何属性对返回的列表进行排序。 |
cursor
| UserWhereUniqueInput | 否 | 指定列表的位置(该值通常指定一个id 或其他唯一值)。 |
获取 | 数量 | 否 | 指定列表中应返回多少个对象(从开头(正值)或结尾(负值)或者如果已提及,则从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
) - 所有具有非 `null` `name` 字段的记录的计数
- 所有具有非 `null` `city` 字段的记录的计数
const c = await prisma.user.count({
select: {
_all: true,
city: true,
name: true,
},
});
aggregate()
另请参阅:聚合、分组和汇总
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
where | UserWhereInput | 否 | 将所有模型字段包装在类型中,以便可以通过任何属性过滤列表。 |
orderBy | XOR<Enumerable<UserOrderByInput>, UserOrderByInput> | 否 | 允许您按任何属性对返回的列表进行排序。 |
cursor
| UserWhereUniqueInput | 否 | 指定列表的位置(该值通常指定一个id 或其他唯一值)。 |
获取 | 数量 | 否 | 指定列表中应返回多少个对象(从开头(正值)或结尾(负值)或者如果已提及,则从cursor 位置开始查看)。 |
跳过 | 数量 | 否 | 指定应跳过列表中返回对象的多少个。 |
_count | true | 否 | 返回匹配记录或非 `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 的组。 |
获取 | 数量 | 否 | 指定列表中应返回多少个对象(从开头(正值)或结尾(负值)或者如果已提及,则从cursor 位置开始查看)。 |
跳过 | 数量 | 否 | 指定应跳过列表中返回对象的多少个。 |
_count | true | UserCountAggregateInputType | 否 | 返回匹配记录或非 `null` 字段的计数。 |
_avg | UserAvgAggregateInputType | 否 | 返回指定字段所有值的平均值。 |
_sum | UserSumAggregateInputType | 否 | 返回指定字段所有值的总和。 |
_min | UserMinAggregateInputType | 否 | 返回指定字段的最小可用值。 |
_max | UserMaxAggregateInputType | 否 | 返回指定字段的最大可用值。 |
示例
按 `country` / `city` 分组,其中平均 `profileViews` 大于 `200`,并返回每个组的 `profileViews` 的 `_sum`
查询还返回每个组中 `_all` 记录的计数,以及每个组中所有具有非 `null` `city` 字段值的记录。
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,
},
},
},
});
include
在 `select` 中
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: '[email protected]',
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` 选项目前处于预览阶段,您需要通过 Prisma 模式文件中的 `omitApi` 预览功能标志启用它
generator client {
provider = "prisma-client-js"
previewFeatures = ["omitApi"]
}
添加此标志后,您需要再次运行 `prisma generate` 以重新生成 Prisma Client。
备注
- 您不能组合 `omit` 和 `select`,因为它们具有相反的目的
示例
从所有 `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
选项目前处于预览阶段,您需要通过Prisma模式文件中的relationJoins
预览功能标志启用它。
generator client {
provider = "prisma-client-js"
previewFeatures = ["relationJoins"]
}
添加此标志后,您需要再次运行prisma generate
来重新生成Prisma Client。此功能目前在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: '[email protected]',
},
},
],
}); -
UserWhereUniqueInput
此类型通过公开模型上的任何唯一字段来工作。分配了@id
的字段被视为唯一字段,分配了@unique
的字段也是如此。从 4.5.0 版本开始,此类型公开了模型上的所有字段。这意味着当您根据唯一字段过滤单个记录时,您可以同时检查其他非唯一和唯一字段。了解更多。
// UserWhereUniqueInput
const whereEmailIsUnique = Prisma.validator<Prisma.UserWhereUniqueInput>()({
email: '[email protected]',
}) -
PostScalarWhereInput
const 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
- 此类型将更新其中id匹配的Post
记录的title字段,如果不存在,则会创建它。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
- 此类型将更新所有其中published设置为false的Post
记录。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
一起使用。
UserOrderByInput
const orderEmailsByDescending = Prisma.validator<Prisma.UserOrderByInput>()({
email: 'desc',
});
distinct
对来自 findMany
或 findFirst
的记录列表进行去重。另请参阅:聚合、分组和汇总
示例
对单个字段进行去重选择
以下示例返回所有不同的 city
字段,并且仅选择 city
和 country
字段
const distinctCities = await prisma.user.findMany({
select: {
city: true,
country: true,
},
distinct: ['city'],
});
[
{ city: 'Paris', country: 'France' },
{ city: 'Lyon', country: 'France' },
];
对多个字段进行去重选择
以下示例返回所有不同的 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' },
];
请注意,现在除了“巴黎,法国”之外,还有一个“巴黎,丹麦”。
结合过滤器进行去重选择
以下示例返回所有不同的 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'],
});
嵌套查询
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: '[email protected]',
profile: {
create: { bio: 'Hello World' },
},
},
});
创建具有新 User
记录的新 Profile
记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
create: { email: '[email protected]' },
},
},
})
创建具有新 Post
记录的新 User
记录
const user = await prisma.user.create({
data: {
email: '[email protected]',
posts: {
create: { title: 'Hello World' },
},
},
});
创建具有两个新 Post
记录的新 User
记录
由于它是一对多关系,您还可以通过将数组传递给 create
来一次创建多个 Post
记录。
const user = await prisma.user.create({
data: {
email: '[email protected]',
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: '[email protected]' },
data: {
profile: {
create: { bio: 'Hello World' },
},
},
});
通过创建新的 Post
记录更新现有的 User
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
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
。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
数据 | Enumerable<UserCreateManyInput> | 是 | 将所有模型字段包装在一个类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
skipDuplicates? | boolean | 否 | 不要插入具有唯一字段或已存在 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: '[email protected]' },
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.
示例
创建新的 Profile
记录并通过唯一字段将其连接到现有的 User
记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
connect: { email: '[email protected]' },
},
},
});
创建新的 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: '[email protected]' },
},
},
});
通过将其连接到现有的 Profile
记录来更新现有的 User
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
connect: { id: 24 },
},
},
});
通过将其连接到两个现有的 Post
记录来更新现有的 User
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
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 连接到一个电子邮件地址为
[email protected]
的User
- 如果不存在匹配的用户,则创建一个新的用户
const user = await prisma.profile.create({
data: {
bio: 'The coolest Alice on the planet',
user: {
connectOrCreate: {
where: { email: '[email protected]' },
create: { email: '[email protected]'}
},
},
})
创建一个新的Post
记录并将其连接到现有的User
记录,或创建一个新的User
const user = await prisma.post.create({
data: {
title: 'Hello World',
author: {
connectOrCreate: {
where: { email: '[email protected]' },
create: { email: '[email protected]' },
},
},
},
});
更新现有的User
记录,将其连接到现有的Profile
记录,或创建一个新的Profile
记录
以下示例
- 尝试将用户连接到
id
为20
的Profile
- 如果不存在匹配的 Profile,则创建一个新的 Profile
const updateUser = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
connectOrCreate: {
where: { id: 20 },
create: {
bio: 'The coolest Alice in town',
},
},
},
},
});
更新现有的User
记录,将其连接到两个现有的Post
记录,或创建两个新的Post
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
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.
-
示例
更新现有的User
记录,断开它连接到的Profile
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
disconnect: true,
},
},
});
更新现有的User
记录,断开它连接到的两个Post
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
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.")
示例
更新现有的User
记录,更新它连接到的Profile
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
update: { bio: 'Hello World' },
},
},
});
更新现有的User
记录,更新它连接到的两个Post
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
posts: {
update: [
{
data: { published: true },
where: { id: 32 },
},
{
data: { published: true },
where: { id: 23 },
},
],
},
},
});
upsert
本节介绍在update()
中使用嵌套 upsert 的方法。要了解upsert()
操作,请参考链接文档。
嵌套的upsert
查询会在相关记录存在时更新它,或创建一个新的相关记录。
示例
更新现有的User
记录,更新它连接到的Profile
记录或创建一个新的(upsert)
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
upsert: {
create: { bio: 'Hello World' },
update: { bio: 'Hello World' },
},
},
},
});
更新现有的User
记录,更新它连接到的两个Post
记录或创建新的(upsert)
const user = await prisma.user.update({
where: { email: '[email protected]' },
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
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
delete: true,
},
},
});
更新现有的User
记录,删除它连接到的两个Post
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
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: {},
},
},
});
过滤条件和运算符
- 从 4.3.0 版本开始,您还可以使用这些运算符比较同一模型中的字段使用
<model>.fields
属性。 - 在 4.3.0 之前的版本中,您可以使用原始查询比较同一模型中的字段。
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
}
},
});
not
值不等于n
。
示例
返回所有name
**不**等于"Eleanor"
的用户
const result = await prisma.user.findMany({
where: {
name: {
not: 'Eleanor',
},
},
});
not
将返回所有与给定值不匹配的项。但是,如果列是可空的,则不会返回NULL
值。如果您需要返回空值,请使用OR
运算符包含NULL
值。
返回所有name
不等于"Eleanor"
的用户,**包括**name
为NULL
的用户
await prisma.user.findMany({
where: {
OR: [
{ name: { not: 'Eleanor' } },
{ name: null }
]
}
})
in
值n
存在于列表中。
不会返回null
值。例如,如果您组合使用in
和NOT
来返回名称**不**在列表中的用户,则不会返回名称值为null
的用户。
示例
获取User
记录,其中id
可以在以下列表中找到:[22, 91, 14, 2, 5]
const getUser = await prisma.user.findMany({
where: {
id: { in: [22, 91, 14, 2, 5] },
},
});
获取User
记录,其中name
可以在以下列表中找到:['Saqui', 'Clementine', 'Bob']
const getUser = await prisma.user.findMany({
where: {
name: { in: ['Saqui', 'Clementine', 'Bob'] },
},
});
获取User
记录,其中name
不在列表中
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
值。
示例
获取User
记录,其中id
**无法**在以下列表中找到:[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
开头的Post
记录(例如Prisma
)
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
。
示例
获取所有Post
记录,其中title
字段包含Prisma
或databases
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
},
});
获取所有Post
记录,其中title
字段包含Prisma
或databases
,但不包含SQL
以下示例结合了OR
和NOT
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
NOT: {
title: {
contains: 'SQL',
},
},
},
});
获取所有Post
记录,其中title
字段包含Prisma
或databases
,并且published
为false
以下示例结合了OR
和AND
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
AND: {
published: false,
},
},
});
NOT
所有条件必须返回false
。
示例
获取所有Post
记录,其中title
不包含SQL
const result = await prisma.post.findMany({
where: {
NOT: {
title: {
contains: 'SQL',
},
},
},
});
获取所有Post
记录,其中title
字段包含Prisma
或databases
,但不包含SQL
,并且关联的User
记录的电子邮件地址不包含sarah
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)。
示例
获取所有Post
记录,其中用户的姓名为"Bob"
const result = await prisma.post.findMany({
where: {
user: {
is: {
name: "Bob"
},
}
}
}
isNot
返回所有记录,其中关联记录不匹配过滤条件(例如,用户的姓名isNot
Bob)。
示例
获取所有Post
记录,其中用户的姓名不为"Bob"
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
此方法仅在版本3.11.1及更高版本的MongoDB中可用。
使用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
给定值存在于列表中。
示例
以下查询返回所有Post
记录,其中tags
列表包含"databases"
const posts = await client.post.findMany({
where: {
tags: {
has: 'databases',
},
},
});
以下查询返回所有Post
记录,其中tags
列表不包含"databases"
const posts = await client.post.findMany({
where: {
NOT: {
tags: {
has: 'databases',
},
},
},
});
hasEvery
每个值都存在于列表中。
示例
以下查询返回所有Post
记录,其中tags
列表至少包含"databases"
和"typescript"
const posts = await prisma.post.findMany({
where: {
tags: {
hasEvery: ['databases', 'typescript'],
},
},
});
hasSome
列表中至少存在一个值。
示例
以下查询返回所有 Post
记录,其中 tags
列表包含 "databases"
或 "typescript"
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
将排除根本未设置的未定义结果。
示例
以下查询返回所有 Post
记录,其中 tags
已设置为 null
或某个值
const posts = await prisma.post.findMany({
where: {
tags: {
isSet: true,
},
},
});
equals
列表完全匹配给定值。
示例
以下查询返回所有 Post
记录,其中 tags
列表仅包含 "databases"
和 "typescript"
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
复合类型的 zip 字段
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
不存在,则创建一个新的 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
过滤复合类型列表,其中列表中的每个项目都匹配条件
示例
查找每张照片的 height
都为 200
的第一个产品
const product = prisma.product.findFirst({
where: {
photos: {
every: {
{ height: 200 },
}
}
},
})
some
使用 some
过滤复合类型列表,其中列表中的一个或多个项目匹配条件。
示例
查找一张或多张照片的 url
为 2.jpg
的第一个产品
const product = prisma.product.findFirst({
where: {
photos: {
some: {
{ url: "2.jpg" },
}
}
},
})
none
使用 none
过滤复合类型列表,其中列表中的任何项目都不匹配条件。
示例
查找没有照片的 url
为 2.jpg
的第一个产品
const product = prisma.product.findFirst({
where: {
photos: {
none: {
{ url: "2.jpg" },
}
}
},
})
原子数字运算
更新时的原子操作适用于数字字段类型(Float
和 Int
)。此功能允许您根据字段的**当前**值(例如减去或除以)更新字段,而不会产生竞争条件的风险。
概述:竞争条件
当两个或多个操作必须按顺序执行才能完成任务时,就会发生竞争条件。在以下示例中,两个客户端尝试将同一个字段 (postCount
) 增加 1
客户端 | 操作 | 值 |
---|---|---|
客户端 1 | 获取字段值 | 21 |
客户端 2 | 获取字段值 | 21 |
客户端 2 | 设置字段值 | 22 |
客户端 1 | 设置字段值 | 22 ✘ |
值应该为23
,但两个客户端没有按顺序读取和写入postCount
字段。更新时的原子操作将读取和写入组合到单个操作中,从而防止竞争条件
客户端 | 操作 | 值 |
---|---|---|
客户端 1 | 获取和设置字段值 | 21 → 22 |
客户端 2 | 获取和设置字段值 | 22 → 23 ✔ |
运算符
选项 | 描述 |
---|---|
增量 | 将n 添加到当前值。 |
减量 | 从当前值中减去n 。 |
乘法 | 将当前值乘以n 。 |
除法 | 将当前值除以n 。 |
设置 | 设置当前字段值。与{ 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
数组包含名称值为"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',
},
},
});
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
$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
参数中
如果您将 groupBy 模型查询与 having
选项一起使用,则必须将引用的字段放在 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: "[email protected]" }, { email: "[email protected]" }] },
// ^^^ Valid: the expression specifies a unique field (`id`) outside of any boolean operators
data: { ... }
})
// SQL equivalent:
// WHERE id = 1 AND (email = "[email protected]" OR email = "[email protected]")
以下示例无效,因为在任何布尔运算符之外都没有唯一字段
await prisma.user.update({
where: { OR: [{ email: "[email protected]" }, { email: "[email protected]" }] },
// ^^^ Invalid: the expressions does not contain a unique field outside of boolean operators
data: { ... }
})
一对一关系
从 4.5.0 版本开始,您可以在以下操作中对 一对一关系中的非唯一字段进行过滤
- 嵌套更新
- 嵌套插入或更新
- 嵌套断开连接
- 嵌套删除
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" } } }
}
}
})
嵌套插入或更新示例
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 可以将所有查询作为单个事务传递到查询引擎。