跳至主要内容

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
}

所有示例生成的类型(如 UserSelectUserWhereUniqueInput)都基于 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 事件类型

index.d.ts
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,paramsduration 字段将为 undefined。

所有其他日志级别事件类型

index.d.ts
export type LogEvent = {
timestamp: Date
message: string
target: string
}

示例

queryinfo 记录到 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)
})
展示CLI结果
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)
})
展示CLI结果
infowarnerror 事件记录到控制台
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)
})
展示CLI结果

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

定义 驱动程序适配器 的实例。另请参见 数据库驱动程序

info

这在 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

info

注意rejectOnNotFound 在 v5.0.0 中已删除。

已弃用:rejectOnNotFound 在 v4.0.0 中已弃用。从 v4.0.0 开始,使用查询 findUniqueOrThrowfindFirstOrThrow

使用 rejectOnNotFound 参数配置 findUnique() 和/或 findFirst 以在未找到记录时抛出错误。默认情况下,这两个操作在未找到记录时都返回 null

说明

选项

选项描述
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

info

注意transactionOptions 在 v5.10.0 中引入。

允许在构造函数级别全局设置 事务选项

备注

  • 事务级别可以在每个事务级别上覆盖。

选项

选项描述
maxWaitPrisma 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

备注

选项

名称示例类型(User必需描述
whereUserWhereUniqueInput包装模型的所有唯一字段,以便可以选择单个记录。
从版本 4.5.0 开始,此类型包装模型的所有字段。 了解更多
selectXOR<UserSelect, null>指定要包含在返回对象中的属性
includeXOR<UserInclude, null>指定在返回对象上应急加载哪些关系
omitXOR<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" }使用 selectinclude 来确定要返回哪些字段。
nullnull未找到记录
错误如果 rejectOnNotFound 为 true,则 findUnique() 会抛出错误(默认情况下为 NotFoundError全局可定制),而不是返回 null

示例

获取 id42User 记录
const result = await prisma.user.findUnique({
where: {
id: 42,
},
})
获取 email[email protected]User 记录
const result = await prisma.user.findUnique({
where: {
email: '[email protected]',
},
})
获取 firstNameAlicelastNameSmithUser 记录(@@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',
},
},
})
获取 firstNameAlicelastNameSmithUser 记录(@@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()

info

我们在 v4.0.0 中引入了 findUniqueOrThrow。它替换了 rejectOnNotFound 选项。rejectOnNotFound 在 v4.0.0 中已弃用。

findUniqueOrThrow 以与 findUnique() 相同的方式检索单个数据记录。但是,如果查询未找到记录,它将返回 NotFoundError: No User found error

findUniqueOrThrowfindUnique() 的不同之处在于

  • 它的返回类型是非空类型。例如,post.findUnique() 可以返回 postnull,但 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必需描述
selectXOR<UserSelect, null>指定要包含在返回对象中的属性
includeXOR<UserInclude, null>指定在返回对象上应急加载哪些关系
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。在 预览 中,自 5.13.0 起
relationLoadStrategy'join''query'默认:join。指定 关系查询的加载策略。仅在与 include(或关系字段上的 select)结合使用时可用。在 预览 中,自 5.9.0 起。
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性过滤列表。
orderByXOR<Enumerable<User
OrderByInput>,UserOrderByInput>
允许您按任何属性对返回的列表进行排序。
cursorUserWhereUniqueInput指定列表的位置(该值通常指定一个 id 或其他唯一值)。
takenumber指定列表中应返回多少个对象。与 findFirst 一起使用时,take 隐式为 1-1findFirst 仅受值是正数还是负数的影响 - 任何负值都会反转列表。
skipnumber指定列表中应跳过多少个返回的对象。
distinctEnumerable<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" }使用 selectinclude 来确定要返回哪些字段。
nullnull未找到记录
错误如果 rejectOnNotFound 为 true,则 findUnique() 会抛出错误(默认情况下为 NotFoundError全局可定制),而不是返回 null

备注

  • findFirst 在幕后调用 findMany 并接受相同的查询选项。
  • 使用 findFirst 查询时传入负的 take 值会反转列表的顺序。

示例

有关如何过滤结果的示例,请参阅 过滤器条件和运算符

获取 nameAlice 的第一个 User 记录
const user = await prisma.user.findFirst({
where: { name: 'Alice' },
})
获取 titleA 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()

info

我们在 v4.0.0 中引入了 findFirstOrThrow。它替换了 rejectOnNotFound 选项。rejectOnNotFound 在 v4.0.0 中已弃用。

findFirstOrThrow 以与 findFirst 相同的方式检索列表中的第一条记录。但是,如果查询未找到记录,它将返回 NotFoundError: No User found error

findFirstOrThrowfindFirst 的不同之处在于

  • 它的返回类型是非空类型。例如,post.findFirst() 可以返回 postnull,但 post.findFirstOrThrow 始终返回 post

  • 它与 $transaction API 中的顺序操作不兼容。如果查询返回 NotFoundError,则 API 不会回滚调用数组中的任何操作。作为一种解决方法,您可以使用交互式事务与 $transaction API,如下所示

    prisma.$transaction(async (tx) => {
    await tx.model.create({ data: { ... });
    await tx.model.findFirstOrThrow();
    })

findMany()

findMany 返回一个记录列表。

选项

名称类型必需描述
selectXOR<PostSelect, null>指定要包含在返回对象中的属性
includeXOR<PostInclude, null>指定在返回对象上应急加载哪些关系
omitXOR<PostOmit, null>指定要从返回对象中排除的属性。在 预览 中,自 5.13.0 起
relationLoadStrategy'join''query'默认:join。指定 关系查询的加载策略。仅在与 include(或关系字段上的 select)结合使用时可用。在 预览 中,自 5.9.0 起。
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性过滤列表。
orderByXOR<Enumerable<PostOrder
ByInput>, PostOrderByInput>
允许您按任何属性对返回的列表进行排序。
cursorUserWhereUniqueInput指定列表的位置(该值通常指定一个 id 或其他唯一值)。
takenumber指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)cursor 位置(如果已提及)开始)。
skipnumber指定列表中应跳过多少个返回的对象。
distinctEnumerable<UserDistinctFieldEnum>允许您按特定字段过滤掉重复的行 - 例如,仅返回不同的 Post 标题。

返回类型

返回类型示例描述
JavaScript 数组对象(类型化)User[]
JavaScript 数组对象(纯)[{ title: "Hello world" }]使用 selectinclude 来确定要返回哪些字段。
空数组[]未找到匹配的记录。

示例

有关如何过滤结果的示例,请参阅 过滤器条件和运算符

获取所有nameAliceUser记录
const user = await prisma.user.findMany({
where: { name: 'Alice' },
})

create()

create创建一个新的数据库记录。

选项

名称类型必需描述
数据XOR<UserCreateInput,
UserUncheckedCreateInput>
将所有模型字段封装在一个类型中,以便在创建新记录时提供它们。 它还包含关系字段,使您可以执行(事务性)嵌套插入。 在数据模型中标记为可选或具有默认值的字段是可选的。
selectXOR<UserSelect, null>指定要包含在返回对象中的属性
includeXOR<UserInclude, null>指定在返回对象上应急加载哪些关系
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。在 预览 中,自 5.13.0 起
relationLoadStrategy'join''query'默认:join。指定 关系查询的加载策略。仅在与 include(或关系字段上的 select)结合使用时可用。在 预览 中,自 5.9.0 起。

返回类型

返回类型示例描述
JavaScript 对象(类型化)User
JavaScript 对象(纯){ name: "Alice Wonderland" }使用 selectinclude 来确定要返回哪些字段。

备注

  • 您还可以执行嵌套的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)
})
展示CLI结果
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>
将模型的所有字段封装起来,以便在更新现有记录时提供它们。 在数据模型中标记为可选或具有默认值的字段是可选的。
whereUserWhereUniqueInput包装模型的所有唯一字段,以便可以选择单个记录。
从版本 4.5.0 开始,此类型包装模型的所有字段。 了解更多
selectXOR<UserSelect, null>指定要包含在返回对象中的属性
includeXOR<UserInclude, null>指定在返回对象上应急加载哪些关系
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。在 预览 中,自 5.13.0 起
relationLoadStrategy'join''query'默认:join。指定 关系查询的加载策略。仅在与 include(或关系字段上的 select)结合使用时可用。在 预览 中,自 5.9.0 起。

返回类型

返回类型示例描述
JavaScript 对象(类型化)User
JavaScript 对象(纯){ name: "Alice Wonderland" }使用 selectinclude 来确定要返回哪些字段。
RecordNotFound异常如果记录不存在,则会抛出异常。

备注

  • 要对更新执行算术运算(加、减、乘、除),请使用原子更新来防止竞争条件。
  • 您还可以执行嵌套的update - 例如,同时更新用户及其帖子。

示例

id1User记录的email更新为[email protected]
const user = await prisma.user.update({
where: { id: 1 },
data: { email: '[email protected]' },
})

upsert()

info

本节介绍upsert()操作的使用方法。 要了解如何在update()中使用嵌套upsert查询,请参考链接文档。

upsert执行以下操作

  • 如果现有的数据库记录满足where条件,则更新该记录
  • 如果没有任何数据库记录满足where条件,则创建一个新的数据库记录

选项

名称类型必需描述
创建XOR<UserCreateInput,
UserUncheckedCreateInput>
将模型的所有字段封装起来,以便在创建新记录时提供它们。 它还包含关系字段,使您可以执行(事务性)嵌套插入。 在数据模型中标记为可选或具有默认值的字段是可选的。
更新XOR<UserUpdateInput,
UserUncheckedUpdateInput>
将模型的所有字段封装起来,以便在更新现有记录时提供它们。 在数据模型中标记为可选或具有默认值的字段是可选的。
whereUserWhereUniqueInput包装模型的所有唯一字段,以便可以选择单个记录。
从版本 4.5.0 开始,此类型包装模型的所有字段。 了解更多
selectXOR<UserSelect, null>指定要包含在返回对象中的属性
includeXOR<UserInclude, null>指定在返回对象上应急加载哪些关系
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。在 预览 中,自 5.13.0 起
relationLoadStrategy'join''query'默认:join。指定 关系查询的加载策略。仅在与 include(或关系字段上的 select)结合使用时可用。在 预览 中,自 5.9.0 起。

返回类型

返回类型示例描述
JavaScript 对象(类型化)User
JavaScript 对象(纯){ name: "Alice Wonderland" }使用 selectinclude 来确定要返回哪些字段。

备注

  • 要对更新执行算术运算(加、减、乘、除),请使用原子更新来防止竞争条件。
  • 如果两个或多个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

为了使用数据库 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

  • upsertcreateupdate选项中没有嵌套查询
  • 该查询包含使用嵌套读取的选择
  • 该查询只修改一个模型
  • upsertwhere选项中只有一个唯一字段
  • 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]',
},
})

在以下查询中,poststitle字段的选择是嵌套读取,因此 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

选项

名称类型必需描述
whereUserWhereUniqueInput包装模型的所有唯一字段,以便可以选择单个记录。
从版本 4.5.0 开始,此类型包装模型的所有字段。 了解更多
selectXOR<UserSelect, null>指定要包含在返回对象中的属性
includeXOR<UserInclude, null>指定在返回对象上应急加载哪些关系
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。在 预览 中,自 5.13.0 起
relationLoadStrategy'join''query'默认:join。指定 关系查询的加载策略。仅在与 include(或关系字段上的 select)结合使用时可用。在 预览 中,自 5.9.0 起。

返回类型

返回类型示例描述
JavaScript 对象(类型化)User被删除的User记录。
JavaScript 对象(纯){ name: "Alice Wonderland" }被删除的User记录中的数据。 使用selectinclude来确定要返回哪些字段。
RecordNotFound异常如果记录不存在,则会抛出异常。

备注

  • 要根据某些条件删除多个记录(例如,所有email地址为prisma.ioUser记录,请使用deleteMany

示例

删除id1User记录
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,
},
})
展示CLI结果
{ "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。

info

createManyAndReturn() 仅在 Prisma ORM 版本 5.14.0 及更高版本中可用。createManyAndReturn() 仅适用于 PostgreSQL、CockroachDB 和 SQLite。

选项

名称类型必需描述
数据Enumerable<UserCreateManyInput>将所有模型字段封装在一个类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。
selectXOR<UserSelect, null>指定要包含的属性 在返回的 objects 上。
omitXOR<UserOmit, null>指定要排除的属性 在返回的 objects 上。在 预览 中,从 5.13.0 开始。与 `select` 互斥。
includeXOR<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]' },
],
})
展示CLI结果
[
{ "id": 0, "name": "Sonali", "email": "[email protected]", "profileViews": 0 },
{ "id": 1, "name": "Alex", "email": "[email protected]", "profileViews": 0 }
]

updateMany()

updateMany 批量更新一批现有的数据库记录,并返回更新的记录数量。

选项

名称类型必需描述
数据XOR<UserUpdateManyMutationInput,
UserUncheckedUpdateManyInput>
将模型的所有字段封装起来,以便在更新现有记录时提供它们。在 `data` 上,标记为可选或在数据模型中具有默认值的字段是可选的。
whereUserWhereInput将模型的 *所有* 字段封装起来,以便可以使用任何属性过滤列表。如果你不筛选列表,所有记录都将被更新。

返回值类型

返回类型示例描述
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 在事务中删除多个记录。

选项

名称类型必需描述
whereUserWhereInput将模型的 *所有* 字段封装起来,以便可以使用任何字段过滤列表。

返回值类型

返回类型示例描述
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()

选项

名称类型必需描述
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性过滤列表。
orderByXOR<Enumerable<PostOrder
ByInput>, PostOrderByInput>
允许您按任何属性对返回的列表进行排序。
cursorUserWhereUniqueInput指定列表的位置(该值通常指定一个 id 或其他唯一值)。
takenumber指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)cursor 位置(如果已提及)开始)。
skipnumber指定列表中应跳过多少个返回的对象。

返回值类型

返回类型示例描述
number29记录数量。
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()

另请参阅:聚合、分组和汇总

选项

名称类型必需描述
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性过滤列表。
orderByXOR<Enumerable<UserOrderByInput>,
UserOrderByInput>
允许您按任何属性对返回的列表进行排序。
cursorUserWhereUniqueInput指定列表的位置(该值通常指定一个 id 或其他唯一值)。
takenumber指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)cursor 位置(如果已提及)开始)。
skipnumber指定列表中应跳过多少个返回的对象。
_counttrue返回匹配记录或非 `null` 字段的计数。
_avgUserAvgAggregateInputType返回指定字段的所有值的平均值。
_sumUserSumAggregateInputType返回指定字段的所有值的总和。
_minUserMinAggregateInputType返回指定字段的最小可用值。
_maxUserMaxAggregateInputType返回指定字段的最大可用值。

示例

返回所有 `User` 记录的 `profileViews` 的 `_min`、`_max` 和 `_count`
const minMaxAge = await prisma.user.aggregate({
_count: {
_all: true,
},
_max: {
profileViews: true,
},
_min: {
profileViews: true,
},
})
展示CLI结果
返回所有 `User` 记录的所有 `profileViews` 的 `_sum`
const setValue = await prisma.user.aggregate({
_sum: {
profileViews: true,
},
})
展示CLI结果

groupBy()

另请参阅:聚合、分组和汇总

选项

名称类型必需描述
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性过滤列表。
orderByXOR<Enumerable<UserOrderByInput>,
UserOrderByInput>
允许你按 `by` 中也存在的任何属性对返回的列表进行排序。
byArray<UserScalarFieldEnum> | string指定要按其对记录进行分组的字段或字段组合。
havingUserScalarWhereWithAggregatesInput允许你通过聚合值过滤组 - 例如,仅返回平均年龄小于 50 的组。
takenumber指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)cursor 位置(如果已提及)开始)。
skipnumber指定列表中应跳过多少个返回的对象。
_counttrue | UserCountAggregateInputType返回匹配记录或非 `null` 字段的计数。
_avgUserAvgAggregateInputType返回指定字段的所有值的平均值。
_sumUserSumAggregateInputType返回指定字段的所有值的总和。
_minUserMinAggregateInputType返回指定字段的最小可用值。
_maxUserMaxAggregateInputType返回指定字段的最大可用值。

示例

按 `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,
},
},
},
})
展示CLI结果
;[
{
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 返回的对象中包含哪些字段。参见:选择字段和包含关系

备注

示例

选择单个 User 记录的 nameprofileViews 字段
const result = await prisma.user.findUnique({
where: { id: 1 },
select: {
name: true,
profileViews: true,
},
})
展示CLI结果
选择多个 User 记录的 emailrole 字段
const result = await prisma.user.findMany({
select: {
email: true,
role: true,
},
})
展示CLI结果
选择关系的 _count
const usersWithCount = await prisma.user.findMany({
select: {
_count: {
select: { posts: true },
},
},
})
展示CLI结果
选择相关 Post 记录的 'id' 和 'title' 字段
const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
select: {
id: true,
title: true,
},
},
},
})
展示CLI结果
includeselect
const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
include: {
author: true,
},
},
},
})
展示CLI结果

select 的生成类型

以下示例演示了如何将 validatorselect 一起使用

const selectNameEmailNotPosts = Prisma.validator<Prisma.UserSelect>()({
name: true,
email: true,
posts: false,
})

include

include 定义了 Prisma Client 返回的结果中包含哪些关系。参见:选择字段和包含关系

备注

示例

在加载 User 记录时包含 postsprofile 关系
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 的生成类型

以下示例演示了如何将 validatorinclude 一起使用

const includePosts = Prisma.validator<Prisma.UserInclude>()({
posts: true,
})
包含关系的 _count
const usersWithCount = await prisma.user.findMany({
include: {
_count: {
select: { posts: true },
},
},
})
展示CLI结果

omit (预览)

omit 定义了 Prisma Client 返回的对象中排除哪些字段。

由于 omit 选项目前处于预览阶段,您需要通过 Prisma 架构文件中的 omitApi 预览功能标志启用它

generator client {
provider = "prisma-client-js"
previewFeatures = ["omitApi"]
}

添加此标志后,您需要再次运行 prisma generate 来重新生成 Prisma Client。

备注

  • 您不能组合 omitselect,因为它们的作用相反

示例

从所有 User 记录中省略 password 字段
const result = await prisma.user.findMany({
omit: {
password: true,
},
})
展示CLI结果
从所有 Userposts 关系中省略 title 字段
const results = await prisma.user.findMany({
omit: {
password: true,
},
include: {
posts: {
omit: {
title: true,
},
},
},
})
展示CLI结果

omit 的生成类型

以下示例演示了如何将 validatoromit 一起使用

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 的生成类型

以下示例演示了如何将 validatorwhere 一起使用

  • 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 模型上的任何字段,除了 AuthorAuthorPost 模型上的标量字段。

    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

对记录列表进行排序。另见:排序

备注

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 记录的 namePost 进行排序

以下查询按用户名对帖子进行排序

const posts = await prisma.post.findMany({
orderBy: {
author: {
name: 'asc',
},
},
})

按相关 User 记录的 namePost 进行排序,将 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',
},
],
})
展示CLI结果

排序参数的顺序很重要 - 以下查询按 role 排序,然后按 email 排序。请注意结果的差异

const users = await prisma.user.findMany({
select: {
email: true,
role: true,
},
orderBy: [
{
role: 'desc',
},
{
email: 'desc',
},
],
})
展示CLI结果
emailUser 进行排序,选择 nameemail

以下示例返回所有 User 记录的 nameemail 字段,按 email 排序

const users3 = await prisma.user.findMany({
orderBy: {
email: 'asc',
},
select: {
name: true,
email: true,
},
})
展示CLI结果
emailUser 记录进行排序,并按 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',
},
},
},
})
展示CLI结果
对一个用户的嵌套 Post 记录列表进行排序

以下示例检索一个 User 记录(通过 ID),以及一个按 title 排序的嵌套 Post 记录列表

const userWithPosts = await prisma.user.findUnique({
where: {
id: 1,
},
include: {
posts: {
orderBy: {
title: 'desc',
},
select: {
title: true,
published: true,
},
},
},
})
展示CLI结果
enum 排序

以下按 role(一个 enum)对所有 User 记录进行排序

const sort = await prisma.user.findMany({
orderBy: {
role: 'desc',
},
select: {
email: true,
role: true,
},
})
展示CLI结果

orderBy 生成的类型

以下示例演示了如何将 validatororderBy 结合使用

  • UserOrderByInput
    const orderEmailsByDescending = Prisma.validator<Prisma.UserOrderByInput>()({
    email: 'desc',
    })

distinct

对来自 findManyfindFirst 的记录列表进行去重。另请参阅:聚合、分组和汇总

示例

对单个字段进行 distinct 选择

以下示例返回所有不同的 city 字段,并仅选择 citycountry 字段

const distinctCities = await prisma.user.findMany({
select: {
city: true,
country: true,
},
distinct: ['city'],
})
展示CLI结果
;[
{ city: 'Paris', country: 'France' },
{ city: 'Lyon', country: 'France' },
]
对多个字段进行 distinct 选择

以下示例返回所有不同的 city country 字段组合,并仅选择 citycountry 字段

const distinctCitiesAndCountries = await prisma.user.findMany({
select: {
city: true,
country: true,
},
distinct: ['city', 'country'],
})
展示CLI结果
;[
{ city: 'Paris', country: 'France' },
{ city: 'Paris', country: 'Denmark' },
{ city: 'Lyon', country: 'France' },
]

请注意,除了“巴黎,法国”之外,现在还有一个“巴黎,丹麦”

将 distinct 与过滤器结合使用

以下示例返回所有不同的 city country 字段组合,其中用户的电子邮件包含 "prisma.io",并仅选择 citycountry 字段

const distinctCitiesAndCountries = await prisma.user.findMany({
where: {
email: {
contains: 'prisma.io',
},
},
select: {
city: true,
country: true,
},
distinct: ['city', 'country'],
})
展示CLI结果

嵌套查询

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 来创建类别(多个帖子对应多个类别)。
  • 您不能嵌套额外的 createcreateMany
  • 允许直接设置外键 - 例如,在帖子中设置 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 的博客文章标签(标签名称必须唯一)

    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',
    },
    },
    },
    },
    })

    如果查询 A 和查询 B 以以下方式重叠,则查询 A 会导致异常

    查询 A(失败 ❌)查询 B(成功 ✅)
    查询命中服务器,启动事务 A查询命中服务器,启动事务 B
    查找 tagName 等于 computing 的记录,未找到记录
    查找 tagName 等于 computing 的记录,未找到记录
    创建 tagName 等于 computing 的记录并连接
    创建 tagName 等于 computing 的记录
    唯一性冲突,记录已由事务 B 创建

    为了解决这种情况,我们建议捕获唯一性冲突异常 (PrismaClientKnownRequestError,错误 P2002) 并重试失败的查询。

示例

创建新的 Profile 记录,然后将其连接到现有的 User 记录 创建新的 User

以下示例

  1. 创建 Profile
  2. 尝试将个人资料连接到电子邮件地址为 [email protected]User
  3. 如果不存在匹配的用户,则创建新的用户
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 记录

以下示例

  1. 尝试将用户连接到 id20Profile
  2. 如果不存在匹配的个人资料,则创建新的个人资料
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

info

本节介绍 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: {},
},
},
})

过滤条件和操作符

info
  • 从 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" 的用户,包括 nameNULL 的用户
await prisma.user.findMany({
where: {
OR: [
{ name: { not: 'Eleanor' } },
{ name: null }
]
}
})

in

n 存在于列表中。

注意

不会返回 null 值。例如,如果您组合使用 inNOT 来返回名称不在列表中的用户,则不会返回 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 不在 列表中

以下示例组合了 inNOT。您也可以使用 notIn

const getUser = await prisma.user.findMany({
where: {
NOT: {
name: { in: ['Saqui', 'Clementine', 'Bob'] },
},
},
})
获取至少包含一个指定 CategoryPostUser 记录
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 小于 9Post 记录
const getPosts = await prisma.post.findMany({
where: {
likes: {
lt: 9,
},
},
})

lte

n 小于等于 x

示例

获取所有 likes 小于或等于 9Post 记录
const getPosts = await prisma.post.findMany({
where: {
likes: {
lte: 9,
},
},
})

gt

n 大于 x

示例

获取所有 likes 大于 9Post 记录
const getPosts = await prisma.post.findMany({
where: {
likes: {
gt: 9,
},
},
})

gte

n 大于等于 x

示例

获取所有 likes 大于或等于 9Post 记录
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 包含 databasesPost 记录
const result = await prisma.post.count({
where: {
content: {
contains: 'databases',
},
},
})
统计所有 content 包含 databasesPost 记录
const result = await prisma.post.count({
where: {
NOT: {
content: {
contains: 'databases',
},
},
},
})

使用 全文搜索String 字段内搜索。

全文搜索目前处于预览阶段,仅适用于PostgreSQLMySQL。要使用 search,您需要启用 fullTextSearch 预览功能。

generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch"]
}

示例

查找所有标题包含 catdog 的帖子。
const result = await prisma.post.findMany({
where: {
title: {
search: 'cat | dog',
},
},
})
查找所有标题包含 catdog 的帖子。
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 包含 prismaPost 记录,不区分大小写
const result = await prisma.post.findMany({
where: {
title: {
contains: 'prisma',
mode: 'insensitive',
},
},
})

startsWith

示例

获取所有 titlePr 开头的 Post 记录(例如 Prisma
const result = await prisma.post.findMany({
where: {
title: {
startsWith: 'Pr',
},
},
})

endsWith

获取所有 emailprisma.io 结尾的 User 记录

const result = await prisma.user.findMany({
where: {
email: {
endsWith: 'prisma.io',
},
},
})

AND

所有条件必须返回 true。或者,将对象列表传递到 where 子句中 - AND 运算符不是必需的

示例

获取所有 content 字段包含 PrismapublishedfalsePost 记录
const result = await prisma.post.findMany({
where: {
AND: [
{
content: {
contains: 'Prisma',
},
},
{
published: {
equals: false,
},
},
],
},
})
获取所有 content 字段包含 PrismapublishedfalsePost 记录(无 AND

以下格式返回与上一个示例相同的结果,**不使用** AND 运算符

const result = await prisma.post.findMany({
where: {
content: {
contains: 'Prisma',
},
published: {
equals: false,
},
},
})
获取所有 title 字段包含 PrismadatabasespublishedfalsePost 记录

以下示例结合了 ORAND

const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
AND: {
published: false,
},
},
})

OR

一个或多个条件必须返回 true

示例

获取所有 title 字段包含 PrismadatabasesPost 记录
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
},
})
获取所有 title 字段包含 Prismadatabases 但不包含 SQLPost 记录

以下示例结合了 ORNOT

const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
NOT: {
title: {
contains: 'SQL',
},
},
},
})
获取所有 title 字段包含 PrismadatabasespublishedfalsePost 记录

以下示例结合了 ORAND

const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
AND: {
published: false,
},
},
})

NOT

所有条件必须返回 false

示例

获取所有 title 字段包含 Prismadatabases 但不包含 SQLPost 记录
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
NOT: {
title: {
contains: 'SQL',
},
},
},
})
获取所有 title 字段包含 Prismadatabases 但不包含 SQL,并且相关 User 记录的电子邮件地址不包含 sarahPost 记录
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 来返回至少有一个关系的所有记录

示例

获取所有 某些 文章提及 PrismaUser 记录
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

返回所有 **零个** 相关记录匹配筛选条件的记录。

备注

示例

获取所有没有文章的 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

push2.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,
},
},
})

标量列表过滤器

标量列表过滤器允许您根据列表/数组字段的内容进行过滤。

警告

适用于

  • 版本 2.15.0 及更高版本的 PostgreSQL
  • 版本 3.9.0 及更高版本的 CockroachDB
  • 版本 3.11.0 及更高版本的 MongoDB

备注

  • 标量列表/数组过滤器 忽略 NULL 。使用 isEmptyNOT 不会返回具有 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 过滤复合类型列表,其中列表中的每个项目都符合条件。

示例

查找第一个所有照片都具有 height200 的产品
const product = prisma.product.findFirst({
where: {
photos: {
every: {
{ height: 200 },
}
}
},
})

some

使用 some 过滤复合类型列表,其中列表中的一个或多个项目符合条件。

示例

查找第一个一个或多个照片具有 url2.jpg 的产品
const product = prisma.product.findFirst({
where: {
photos: {
some: {
{ url: "2.jpg" },
}
}
},
})

none

使用 none 过滤复合类型列表,其中列表中没有项目符合条件。

示例

查找第一个没有照片具有 url2.jpg 的产品
const product = prisma.product.findFirst({
where: {
photos: {
none: {
{ url: "2.jpg" },
}
}
},
})

原子数字操作

更新时的原子操作适用于数字字段类型 (FloatInt)。此功能允许您根据字段的当前值(例如减去除以)更新字段,而不会产生竞争条件。

概述:竞争条件

当两个或多个操作必须按顺序完成才能完成任务时,就会发生竞争条件。在以下示例中,两个客户端尝试将同一个字段 (postCount) 增加 1。

客户端操作
客户端 1获取字段值21
客户端 2获取字段值21
客户端 2设置字段值22
客户端 1设置字段值22

应该23,但两个客户端没有按顺序读取和写入 postCount 字段。更新时的原子操作将读取和写入组合到一个操作中,从而防止竞争条件。

客户端操作
客户端 1获取和设置字段值2122
客户端 2获取和设置字段值2223

运算符

选项描述
incrementn 添加到当前值。
decrement从当前值中减去 n
multiply将当前值乘以 n
divide将当前值除以 n
set设置当前字段值。与 { myField : n } 相同。

备注

  • 每个字段,每个查询只能执行一次原子更新。
  • 如果字段为 null,它将不会被 incrementdecrementmultiplydivide 更新。

示例

将所有 Post 记录的 viewlikes 字段增加 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 字段

警告

PostgreSQLMySQL 支持,它们对 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"]
}
}

备注

path

path 表示特定键的位置。以下查询返回所有嵌套 favourites > dogBreed 键等于 "Rottweiler" 的用户。

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'dogBreed'],
equals: 'Rottweiler',
},
},
})

以下查询返回所有嵌套 owned > cats 数组包含 "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" 的用户。

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'catBreed'],
string_contains: 'Van',
},
},
})

string_starts_with

以下查询返回所有嵌套 favorites > catBreed 键值以 "Turkish" 开头的用户。

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'catBreed'],
string_starts_with: 'Turkish',
},
},
})

string_ends_with

以下查询返回所有嵌套 favorites > catBreed 键值以 "Van" 结尾的用户。

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['favorites', 'catBreed'],
string_ends_with: 'Van',
},
},
})

array_contains

以下查询返回所有 sanctuaries 数组包含值 "RSPCA" 的用户。

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['sanctuaries'],
array_contains: ['RSPCA'],
},
},
})
info

注意:在 PostgreSQL 中,array_contains 的值必须是一个数组,而不是一个字符串,即使数组只包含一个值。

以下查询返回所有 sanctuaries 数组包含给定数组中所有值的的用户。

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['sanctuaries'],
array_contains: ['RSPCA', 'Alley Cat Allies'],
},
},
})

array_starts_with

以下查询返回所有 sanctuaries 数组以值 "RSPCA" 开头的用户。

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['sanctuaries'],
array_starts_with: 'RSPCA',
},
},
})

array_ends_with

以下查询返回所有 sanctuaries 数组以值 "Alley Cat Allies" 结尾的用户。

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: ['sanctuaries'],
array_ends_with: 'Alley Cat Allies',
},
},
})

客户端方法

注意:客户端级方法以 $ 为前缀。

备注

  • $on$use 客户端方法在使用 $extends 扩展的扩展客户端实例中不存在。
警告

扩展客户端 中,客户端方法不一定存在。如果您正在扩展您的客户端,请确保在使用客户端方法(如 $transaction$connect)之前检查是否存在。

此外,如果您使用 $on$use,则需要在扩展您的客户端之前使用这些客户端方法,因为这些方法在扩展客户端中不存在。对于 $use,我们建议您迁移到使用查询扩展

$disconnect()

$disconnect() 方法关闭调用 $connect 时建立的数据库连接,并停止运行 Prisma ORM 的查询引擎的进程。有关 $connect()$disconnect() 的概述,请参阅连接管理

备注

  • $disconnect() 返回一个 Promise,因此您应该在使用 await 关键字的 async 函数中调用它。

$connect()

$connect() 方法通过 Prisma ORM 的查询引擎建立与数据库的物理连接。有关 $connect()$disconnect() 的概述,请参阅连接管理

备注

  • $connect() 返回一个 Promise,因此您应该在使用 await 关键字的 async 函数中调用它。

$on()

警告

$on扩展客户端 中不可用。请迁移到客户端扩展或在扩展您的客户端之前使用 $on 方法。

$on() 方法允许您订阅 日志记录事件退出钩子

$use()

警告

$use扩展客户端 中不可用。请迁移到使用查询扩展或在扩展您的客户端之前使用 $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查询类型 - 例如,createfindMany
args传递给查询的参数 - 例如,wheredataorderBy
dataPath如果您使用 流畅 API,则会填充。
模型模型类型 - 例如,PostUser
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

请参阅:使用原始 SQL ($executeRaw)

$executeRawUnsafe()

请参阅:使用原始 SQL ($executeRawUnsafe())

$runCommandRaw()

请参阅:使用原始 SQL ($runCommandRaw())

$transaction()

请参阅:事务

$metrics

Prisma Client 指标为您提供了对 Prisma Client 如何与您的数据库交互的详细洞察。您可以使用这些洞察来帮助诊断应用程序的性能问题。了解更多信息:指标

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 预览功能提供。

info

在以下情况下,您必须 使用原始查询来比较同一表中的列

  • 如果您使用的版本早于 4.3.0
  • 如果您想使用唯一过滤器,例如 findUniquefindUniqueOrThrow
  • 如果您想将字段与 唯一约束 进行比较
  • 如果您想使用以下运算符之一来比较 MySQL 或 MariaDB 中的 JSON 字段 与另一个字段:gtgteltlte。请注意,您可以使用这些运算符将 JSON 字段与标量值进行比较。此限制仅适用于尝试将 JSON 字段与另一个字段进行比较时。

要比较同一表中的列,请使用 <model>.fields 属性。在以下示例中,查询将返回 prisma.product.quantity 字段中的值小于或等于 prisma.product.warnQuantity 字段中的值的记录。

prisma.product.findMany({
where: { quantity: { lte: prisma.product.fields.warnQuantity } },
})
info

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 中),则可以搜索所有特定字段位于字段列表中的记录。为此,请使用 innotIn 过滤器引用标量列表。例如

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 字段。

在以下示例中,updateOneupdateTwo 首先读取同一记录,然后尝试更新它。数据库仅在 version 中的值与它进行初始读取时的值相同时才执行这些更新。当数据库执行这些更新中的第一个更新(可能是 updateOneupdateTwo,具体取决于时间)时,它会增加 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 时,您必须在布尔运算符 ANDORNOT 之外指定至少一个唯一字段。您仍然可以在过滤器中将这些布尔运算符与任何其他唯一字段或非唯一字段结合使用。

在以下示例中,我们测试了 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 自动使用唯一过滤器来选择相应的相关记录。因此,您不需要在使用 WhereUniqueInputwhere 语句中指定唯一过滤器 生成的类型。相反,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 可以将所有查询作为单个事务传递给查询引擎。