Prisma 客户端 API 参考
Prisma 客户端 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 客户端。数据源名称包含在生成的客户端中。
- 如果您在模式中将
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
字段将为 undefined。
所有其他日志级别事件类型
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 客户端返回的错误的级别和格式。
错误格式
名称 | 描述 |
---|---|
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
这在 driverAdapters
功能标志后面的版本 5.4.0 及更高版本中可用。
示例
以下示例使用 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 起。 |
rejectOnNotFound (已弃用) | RejectOnNotFound | 否 | 如果为 true,则抛出 NotFoundError: No User found error 。您也可以 全局配置 rejectOnNotFound 。注意: rejectOnNotFound 在 v4.0.0 中已弃用。从 v4.0.0 开始,使用 findUniqueOrThrow 代替。 |
返回类型
返回类型 | 示例 | 描述 |
---|---|---|
JavaScript 对象(类型化) | User | |
JavaScript 对象(纯) | { title: "Hello world" } | 使用 select 和 include 来确定要返回哪些字段。 |
null | null | 未找到记录 |
错误 | 如果 rejectOnNotFound 为 true,则 findUnique() 会抛出错误(默认情况下为 NotFoundError ,全局可定制),而不是返回 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
)
展开具有 @@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()
我们在 v4.0.0 中引入了 findUniqueOrThrow
。它替换了 rejectOnNotFound
选项。rejectOnNotFound
在 v4.0.0 中已弃用。
findUniqueOrThrow
以与 findUnique()
相同的方式检索单个数据记录。但是,如果查询未找到记录,它将返回 NotFoundError: No User found error
。
findUniqueOrThrow
与 findUnique()
的不同之处在于
-
它的返回类型是非空类型。例如,
post.findUnique()
可以返回post
或null
,但post.findUniqueOrThrow()
始终返回post
。 -
它与
$transaction
API 中的顺序操作不兼容。如果查询返回NotFoundError
,则 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<User OrderByInput>,UserOrderByInput> | 否 | 允许您按任何属性对返回的列表进行排序。 |
cursor | UserWhereUniqueInput | 否 | 指定列表的位置(该值通常指定一个 id 或其他唯一值)。 |
take | number | 否 | 指定列表中应返回多少个对象。与 findFirst 一起使用时,take 隐式为 1 或 -1 。findFirst 仅受值是正数还是负数的影响 - 任何负值都会反转列表。 |
skip | number | 否 | 指定列表中应跳过多少个返回的对象。 |
distinct | Enumerable<UserDistinct FieldEnum> | 否 | 允许您按特定字段过滤掉重复的行 - 例如,仅返回不同的 Post 标题。 |
rejectOnNotFound (已弃用) | RejectOnNotFound | 否 | 如果为 true,则抛出 NotFoundError: No User found error 。您也可以 全局配置 rejectOnNotFound 。注意: rejectOnNotFound 在 v4.0.0 中已弃用。从 v4.0.0 开始,使用 findFirstOrThrow 代替。 |
返回类型
返回类型 | 示例 | 描述 |
---|---|---|
JavaScript 对象(类型化) | User | 指定要包含在返回对象中的属性。 |
JavaScript 对象(纯) | { title: "Hello world" } | 使用 select 和 include 来确定要返回哪些字段。 |
null | null | 未找到记录 |
错误 | 如果 rejectOnNotFound 为 true,则 findUnique() 会抛出错误(默认情况下为 NotFoundError ,全局可定制),而不是返回 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()
我们在 v4.0.0 中引入了 findFirstOrThrow
。它替换了 rejectOnNotFound
选项。rejectOnNotFound
在 v4.0.0 中已弃用。
findFirstOrThrow
以与 findFirst
相同的方式检索列表中的第一条记录。但是,如果查询未找到记录,它将返回 NotFoundError: No User found error
。
findFirstOrThrow
与 findFirst
的不同之处在于
-
它的返回类型是非空类型。例如,
post.findFirst()
可以返回post
或null
,但post.findFirstOrThrow
始终返回post
。 -
它与
$transaction
API 中的顺序操作不兼容。如果查询返回NotFoundError
,则 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 或其他唯一值)。 |
take | number | 否 | 指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)或从 cursor 位置(如果已提及)开始)。 |
skip | number | 否 | 指定列表中应跳过多少个返回的对象。 |
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
创建一个新的数据库记录。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
数据 | 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 查询交给数据库。 了解更多。
示例
更新(如果存在)或创建一个新的User
记录,其email
为[email protected]
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 异常 | 如果记录不存在,则会抛出异常。 |
备注
- 要根据某些条件删除多个记录(例如,所有
email
地址为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? | 布尔值 | 否 | 不要插入具有唯一字段或 ID 字段的记录,这些字段或 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` 和两个带有嵌套 `createMany` 的 `Post` 记录。
示例
创建多个新用户
const users = await prisma.user.createMany({
data: [
{ name: 'Sonali', email: '[email protected]' },
{ name: 'Alex', email: '[email protected]' },
],
})
createManyAndReturn()
createManyAndReturn
创建多个记录并返回生成的 objects。
createManyAndReturn()
仅在 Prisma ORM 版本 5.14.0 及更高版本中可用。createManyAndReturn()
仅适用于 PostgreSQL、CockroachDB 和 SQLite。
选项
名称 | 类型 | 必需 | 描述 |
---|---|---|---|
数据 | Enumerable<UserCreateManyInput> | 是 | 将所有模型字段封装在一个类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。 |
select | XOR<UserSelect, null> | 否 | 指定要包含的属性 在返回的 objects 上。 |
omit | XOR<UserOmit, null> | 否 | 指定要排除的属性 在返回的 objects 上。在 预览 中,从 5.13.0 开始。与 `select` 互斥。 |
include | XOR<UserInclude, null> | 否 | 指定要急切加载的关联关系 在返回的 objects 上。 |
skipDuplicates? | 布尔值 | 否 | 不要插入具有唯一字段或 ID 字段的记录,这些字段或 ID 字段已经存在。仅受支持使用 ON CONFLICT DO NOTHING 的数据库。这排除了 MongoDB 和 SQLServer |
备注
- SQLite 不支持 `skipDuplicates` 选项。
- 你 **不能** 使用顶级 `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: '[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 或其他唯一值)。 |
take | number | 否 | 指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)或从 cursor 位置(如果已提及)开始)。 |
skip | number | 否 | 指定列表中应跳过多少个返回的对象。 |
返回值类型
返回类型 | 示例 | 描述 |
---|---|---|
number | 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 或其他唯一值)。 |
take | number | 否 | 指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)或从 cursor 位置(如果已提及)开始)。 |
skip | number | 否 | 指定列表中应跳过多少个返回的对象。 |
_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 的组。 |
take | number | 否 | 指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)或从 cursor 位置(如果已提及)开始)。 |
skip | number | 否 | 指定列表中应跳过多少个返回的对象。 |
_count | true | UserCountAggregateInputType | 否 | 返回匹配记录或非 `null` 字段的计数。 |
_avg | UserAvgAggregateInputType | 否 | 返回指定字段的所有值的平均值。 |
_sum | UserSumAggregateInputType | 否 | 返回指定字段的所有值的总和。 |
_min | UserMinAggregateInputType | 否 | 返回指定字段的最小可用值。 |
_max | UserMaxAggregateInputType | 否 | 返回指定字段的最大可用值。 |
示例
按 `country` / `city` 分组,其中平均 `profileViews` 大于 `200`,并返回每个组的 `_sum` `profileViews`
查询还返回每个组中 `_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()
请参阅:使用原始 SQL (findRaw()
).
aggreagateRaw()
参见:使用原始 SQL (aggreagateRaw()
)。
模型查询选项
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
从 预览 进入 通用可用性,join
将普遍成为所有关系查询的默认值。
您可以在此处了解更多关于连接策略的信息 此处。
由于 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
- 此类型将更新Post
记录的 title 字段,其中 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
进行排序
此功能从 3.5.0 版本开始在 PostgreSQL 和 MySQL 中提供。您需要使用 fullTextSearch
预览标志来启用此功能。
以下查询按搜索词 '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
记录列表进行排序
以下示例检索一个 User
记录(通过 ID),以及一个按 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
的记录列表进行去重。另请参阅:聚合、分组和汇总
示例
对单个字段进行 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'],
})
嵌套查询
create
嵌套的 create
查询会将新的相关记录或记录集添加到父记录。参阅:处理关系
备注
- 当您
create()
(prisma.user.create(...)
)新的父记录或update()
(prisma.user.update(...)
)现有的父记录时,create
可以作为嵌套查询使用。 - 您可以使用嵌套的
create
或 嵌套的createMany
来创建多个相关记录。如果您需要skipDuplicates
查询选项,则应使用createMany
。
示例
创建一个新的 User
记录,其中包含一个新的 Profile
记录
const user = await prisma.user.create({
data: {
email: '[email protected]',
profile: {
create: { bio: 'Hello World' },
},
},
})
创建一个新的 Profile
记录,其中包含一个新的 User
记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
create: { email: '[email protected]' },
},
},
})
创建一个新的 User
记录,其中包含一个新的 Post
记录
const user = await prisma.user.create({
data: {
email: '[email protected]',
posts: {
create: { title: 'Hello World' },
},
},
})
创建一个新的 User
记录,其中包含两个新的 Post
记录
由于它是 一对多 关系,您也可以通过将数组传递给 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? | 布尔值 | 否 | 不要插入具有唯一字段或 ID 字段的记录,这些字段或 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
- 尝试将个人资料连接到电子邮件地址为
[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]' },
},
},
},
})
通过将其连接到现有的 Profile
记录或 创建新的 Profile
记录来更新现有 User
记录
以下示例
- 尝试将用户连接到
id
为20
的Profile
- 如果不存在匹配的个人资料,则创建新的个人资料
const updateUser = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
connectOrCreate: {
where: { id: 20 },
create: {
bio: 'The coolest Alice in town',
},
},
},
},
})
通过将其连接到两个现有的 Post
记录或 创建两个新的 Post
记录来更新现有 User
记录
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.
-
示例
通过断开与其连接的 Profile
记录的连接来更新现有 User
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
disconnect: true,
},
},
})
通过断开与其连接的两个 Post
记录的连接来更新现有 User
记录
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.")
示例
通过更新与其连接的 Profile
记录来更新现有 User
记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
update: { bio: 'Hello World' },
},
},
})
通过更新与其连接的两个 Post
记录来更新现有 User
记录
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
查询会更新相关记录(如果存在),或创建新的相关记录。
示例
通过更新与其连接的 Profile
记录或创建新的记录 (upsert) 来更新现有 User
记录
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
不在 列表中
以下示例组合了 in
和 NOT
。您也可以使用 notIn
。
const getUser = await prisma.user.findMany({
where: {
NOT: {
name: { in: ['Saqui', 'Clementine', 'Bob'] },
},
},
})
获取至少包含一个指定 Category
的 Post
的 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 和 MySQL。要使用 search
,您需要启用 fullTextSearch
预览功能。
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch"]
}
示例
查找所有标题包含 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
。
示例
获取所有 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
字段包含 Prisma
或 databases
但不包含 SQL
的 Post
记录
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
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
来返回至少有一个关系的所有记录
示例
获取所有 某些 文章提及 Prisma
的 User
记录
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。
- 您可以推送值列表或仅推送单个值。
示例
将 computing
项目添加到 tags
列表中
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
给定值存在于列表中。
示例
以下查询返回所有 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
此过滤器仅在版本 3.11.1 及更高版本的 MongoDB 上可用。
筛选列表,仅包含已设置(设置为值或显式设置为 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
复合类型的 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
不存在,则创建一个新的,否则更新它
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 ✔ |
运算符
选项 | 描述 |
---|---|
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',
},
},
})
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,则会填充。 |
模型 | 模型类型 - 例如,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: "[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 自动使用唯一过滤器来选择相应的相关记录。因此,您不需要在使用 WhereUniqueInput
的 where
语句中指定唯一过滤器 生成的类型。相反,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 可以将所有查询作为单个事务传递给查询引擎。