跳到主要内容

Prisma Client API 参考

Prisma Client API 参考文档基于以下 schema

model User {
id Int @id @default(autoincrement())
name String?
email String @unique
profileViews Int @default(0)
role Role @default(USER)
coinflips Boolean[]
posts Post[]
city String
country String
profile ExtendedProfile?
pets Json
}

model ExtendedProfile {
id Int @id @default(autoincrement())
userId Int? @unique
bio String?
User User? @relation(fields: [userId], references: [id])
}

model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(true)
author User @relation(fields: [authorId], references: [id])
authorId Int
comments Json
views Int @default(0)
likes Int @default(0)
}

enum Role {
USER
ADMIN
}

所有示例生成的类型(例如 UserSelectUserWhereUniqueInput)都基于 User 模型。

PrismaClient

本节描述了 PrismaClient 构造函数及其参数。

备注

  • 参数在运行时进行验证。

datasources

以编程方式覆盖 schema.prisma 文件中 datasource 块的属性 - 例如,作为集成测试的一部分。另请参阅:数据源

从 5.2.0 版及更高版本开始,您还可以使用 datasourceUrl 属性以编程方式覆盖数据库连接字符串。

属性

示例属性示例值描述
db{ url: 'file:./dev_qa.db' }数据库连接 URL

备注

  • 每次添加或重命名数据源时,都必须重新生成 Prisma Client。数据源名称包含在生成的客户端中。
  • 如果您在 schema 中将 datasource 块命名为其他名称,请将 db 替换为您 datasource 块的名称。

示例

以编程方式覆盖数据源 url
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient({
datasources: {
db: {
url: 'file:./dev_qa.db',
},
},
});

基于以下 datasource

datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}

datasourceUrl

以编程方式覆盖 schema.prisma 文件中的 datasource 块。

属性

选项示例值描述
数据库连接字符串'file:./dev_qa.db'数据库连接 URL

示例

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient({
datasourceUrl: 'postgresql://johndoe:randompassword@localhost:5432/mydb',
});

log

确定日志的类型和级别。另请参阅:日志记录

选项

选项示例
日志级别数组[ "info", "query" ]
日志定义数组[ { level: "info", emit: "event" }, { level: "warn", emit: "stdout" }]
日志级别
名称示例
查询记录 Prisma 运行的所有查询。

对于关系型数据库,这会记录所有 SQL 查询。示例
prisma:query SELECT "public"."User"."id", "public"."User"."email" FROM "public"."User" WHERE ("public"."User"."id") IN (SELECT "t0"."id" FROM "public"."User" AS "t0" INNER JOIN "public"."Post" AS "j0" ON ("j0"."authorId") = ("t0"."id") WHERE ("j0"."views" > $1 AND "t0"."id" IS NOT NULL)) OFFSET $2

对于 MongoDB,这会使用 mongosh shell 格式记录查询。示例
prisma:query db.User.deleteMany({ _id: ( $in: [ “6221ce49f756b0721fc00542”, ], }, })
信息示例
prisma:info Started http server on http://127.0.0.1:58471
警告警告。
错误错误。
发出格式
名称描述
stdout参见:标准输出
事件引发您可以订阅的事件。
事件类型

query 事件类型

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 字段将未定义。

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

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 Client 返回的错误的级别和格式。

错误格式

名称描述
未定义如果未定义,默认值为无颜色。
漂亮启用漂亮的错误格式。
colorless (默认)启用无颜色错误格式。
最小启用最小错误格式。

示例

无错误格式
const prisma = new PrismaClient({
// Defaults to colorless
});
pretty 错误格式
const prisma = new PrismaClient({
errorFormat: 'pretty',
});
colorless 错误格式
const prisma = new PrismaClient({
errorFormat: 'colorless',
});
minimal 错误格式
const prisma = new PrismaClient({
errorFormat: 'minimal',
});

adapter

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

信息

此功能在版本 5.4.0 及更高版本中,并且需要启用 driverAdapters 功能标志。

示例

以下示例使用了 Neon 驱动适配器

import { PrismaNeon } from '@prisma/adapter-neon';
import { PrismaClient } from '@prisma/client';
import dotenv from 'dotenv';

dotenv.config();
const connectionString = `${process.env.DATABASE_URL}`;

const adapter = new PrismaNeon({ connectionString });
const prisma = new PrismaClient({ adapter });

rejectOnNotFound

信息

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

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

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

备注

选项

选项描述
未找到时拒绝全局启用(true / false抛出自定义错误。
每个操作拒绝为每个操作启用(true / false为每个模型、每个操作抛出自定义错误。

示例

findUnique()findFirst 全局启用
const prisma = new PrismaClient({
rejectOnNotFound: true,
});
为特定操作全局启用
const prisma = new PrismaClient({
rejectOnNotFound: {
findUnique: true,
},
});
如果未找到记录,则为每个模型和操作抛出自定义错误
const prisma = new PrismaClient({
rejectOnNotFound: {
findFirst: {
User: (err) => new Error('User error'),
Post: (err) => new Error('Post error!'),
},
findUnique: {
User: (err) => new Error('User error'),
Post: (err) => new Error('Post error!'),
},
},
});

transactionOptions

信息

注意transactionOptions 在 v5.10.0 中引入。

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

备注

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

选项

选项描述
最大等待时间Prisma Client 从数据库获取事务的最大等待时间。默认值为 2 秒。
超时交互式事务在被取消和回滚之前可以运行的最大时间。默认值为 5 秒。
隔离级别设置事务隔离级别。默认情况下,这设置为您数据库中当前配置的值。可用值可能因您使用的数据库而异。

示例

const prisma = new PrismaClient({
transactionOptions: {
isolationLevel: Prisma.TransactionIsolationLevel.Serializable,
maxWait: 5000, // default: 2000
timeout: 10000, // default: 5000
},
});

模型查询

使用模型查询对您的模型执行 CRUD 操作。另请参阅:CRUD

注意:最佳实践是在将任何不受信任的用户数据传递到 Prisma 查询之前,始终对其进行验证和清理。否则,如果类型检查被绕过,可能会导致 SQL 注入或其他注入漏洞。确保用户提供的值不能无意中绕过关键检查。我们强烈建议在应用程序层执行类型检查和输入验证。有关更多详细信息,请参阅自定义验证部分。

findUnique()

findUnique() 查询允许您检索单个数据库记录

  • ID
  • 唯一属性

findUnique()2.12.0 版本中取代了 findOne

备注

选项

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

返回类型

返回类型示例描述
JavaScript 对象(有类型)User
JavaScript 对象(纯文本){ title: "Hello world" }使用 selectinclude 确定要返回的字段。
未找到记录

示例

获取 id42User 记录
const result = await prisma.user.findUnique({
where: {
id: 42,
},
});
获取 emailalice@prisma.ioUser 记录
const result = await prisma.user.findUnique({
where: {
email: 'alice@prisma.io',
},
});
获取 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()

findUniqueOrThrow() 以与 findUnique() 相同的方式检索单个记录。但是,如果查询未找到请求的记录,它会抛出 PrismaClientKnownRequestError

请注意,在 Prisma v6 之前,它会抛出 NotFoundError: No User found error

以下是其用法示例

await prisma.user.findUniqueOrThrow({
where: { id: 1 },
});

findUniqueOrThrow()findUnique() 的区别如下

  • 其返回类型是非空。例如,post.findUnique() 可以返回 postnull,但 post.findUniqueOrThrow() 始终返回 post

  • 它与 $transaction API 中的顺序操作不兼容。如果查询抛出 PrismaClientKnownRequestError,则 API 不会回滚调用数组中的任何操作。作为变通方法,您可以按如下方式使用带有 $transaction API 的交互式事务

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

findFirst()

findFirst 返回列表中符合您条件的第一个记录。

备注

  • 如果您希望查询在未找到记录时抛出错误,请考虑改用 findFirstOrThrow

选项

名称示例类型(User必需描述
selectXOR<UserSelect, null>指定返回对象中要包含的属性
includeXOR<UserInclude, null>指定返回对象中应预加载的关系
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段。
关联加载策略'join''query'默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性筛选列表。
orderByXOR<Enumerable<UserOrderByInput>, UserOrderByInput>允许您按任何属性对返回列表进行排序。

返回类型

返回类型示例描述
JavaScript 对象(有类型)User指定要包含在返回对象中的属性。
JavaScript 对象(纯文本){ title: "Hello world" }使用 selectinclude 确定要返回的字段。
未找到记录

备注

  • 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()

findFirstOrThrow() 以与 findFirst() 相同的方式检索单个数据记录。但是,如果查询未找到记录,它会抛出 PrismaClientKnownRequestError

请注意,在 Prisma v6 之前,它会抛出 NotFoundError: No User found error

findFirstOrThrow()findFirst() 的区别如下

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

  • 它与 $transaction API 中的顺序操作不兼容。如果查询返回 PrismaClientKnownRequestError,则 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 版本起进入预览阶段
关联加载策略'join''query'默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性筛选列表。
orderByXOR<Enumerable<PostOrder
ByInput>, PostOrderByInput>
允许您按任何属性对返回列表进行排序。
游标UserWhereUniqueInput指定列表的位置(值通常指定 id 或其他唯一值)。
take数字指定列表中应返回的对象数量(从列表的开始(正值)或结束(负值)从指定的 cursor 位置开始计算)
跳过数字指定列表中应跳过的返回对象数量。
distinctEnumerable<UserDistinctFieldEnum>允许您按特定字段过滤掉重复行 - 例如,仅返回不重复的 Post 标题。

返回类型

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

示例

请参阅筛选条件和运算符,了解如何筛选结果的示例。

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

create()

create 创建新的数据库记录。

选项

名称类型必需描述
dataXOR<UserCreateInput,
UserUncheckedCreateInput>
将所有模型字段包装在类型中,以便在创建新记录时提供它们。它还包括关系字段,允许您执行(事务性)嵌套插入。在数据模型中标记为可选或具有默认值的字段是可选的。
selectXOR<UserSelect, null>指定返回对象中要包含的属性
includeXOR<UserInclude, null>指定返回对象中应预加载的关系
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段
关联加载策略'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: 'alice@prisma.io' },
});
创建多个新记录

在大多数情况下,您可以使用 createMany()createManyAndReturn() 查询执行批量插入。但是,在某些情况下,create() 是插入多条记录的最佳选择

以下示例会生成两条 INSERT 语句

import { Prisma, PrismaClient } from '@prisma/client';

const prisma = new PrismaClient({ log: ['query'] });

async function main() {
let users: Prisma.UserCreateInput[] = [
{
email: 'ariana@prisma.io',
name: 'Ari',
profileViews: 20,
coinflips: [true, false, false],
role: 'ADMIN',
},
{
email: 'elsa@prisma.io',
name: 'Elsa',
profileViews: 20,
coinflips: [true, false, false],
role: 'ADMIN',
},
];

await Promise.all(
users.map(async (user) => {
await prisma.user.create({
data: user,
});
})
);
}

main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
显示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 更新现有数据库记录。

选项

名称类型必需描述
dataXOR<UserUpdateInput
UserUncheckedUpdateInput>
将模型的所有字段包装在类型中,以便在更新现有记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。
whereUserWhereUniqueInput包装模型的所有字段,以便可以选择记录(了解更多)。
在 4.5.0 版本之前,此类型仅包装模型的唯一字段。
selectXOR<UserSelect, null>指定返回对象中要包含的属性
includeXOR<UserInclude, null>指定返回对象中应预加载的关系
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段。
关联加载策略'join''query'默认值:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用。自 5.9.0 版本起进入预览阶段。

返回类型

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

备注

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

示例

id1User 记录的 email 更新为 alice@prisma.io
const user = await prisma.user.update({
where: { id: 1 },
data: { email: 'alice@prisma.io' },
});

upsert()

信息

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

upsert 执行以下操作

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

选项

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

返回类型

返回类型示例描述
JavaScript 对象(有类型)User
JavaScript 对象(纯文本){ name: "Alice Wonderland" }使用 selectinclude 确定要返回的字段。

备注

  • 要在更新时执行算术运算(加、减、乘、除),请使用原子更新以防止竞态条件。
  • 如果同时发生两个或多个 upsert 操作且记录尚不存在,则可能会发生竞态条件。结果,一个或多个 upsert 操作可能会抛出唯一键约束错误。您的应用程序代码可以捕获此错误并重试该操作。了解更多
  • 从 4.6.0 版本开始,Prisma ORM 会尽可能将 upsert 查询交给数据库处理。了解更多

示例

更新(如果存在)或创建电子邮件为 alice@prisma.io 的新 User 记录
const user = await prisma.user.upsert({
where: { id: 1 },
update: { email: 'alice@prisma.io' },
create: { email: 'alice@prisma.io' },
});

upsert 上的唯一键约束错误

问题

如果同时发生多个 upsert 操作且记录尚不存在,则一个或多个操作可能会返回唯一键约束错误

原因

当 Prisma Client 执行 upsert 操作时,它首先检查该记录是否已存在于数据库中。为了执行此检查,Prisma Client 使用 upsert 操作中的 where 子句执行读取操作。这有两种可能的结果,如下所示

  • 如果记录不存在,则 Prisma Client 创建该记录。
  • 如果记录存在,则 Prisma Client 更新它。

当您的应用程序尝试执行两个或更多并发 upsert 操作时,可能会发生竞态条件,即两个或更多操作未找到记录,因此尝试创建该记录。在这种情况下,其中一个操作成功创建新记录,但其他操作失败并返回唯一键约束错误。

解决方案

在您的应用程序代码中处理 P2002 错误。当它发生时,重试 upsert 操作以更新该行。

数据库 upsert

如果可能,Prisma Client 会将 upsert 查询交给数据库处理。这称为数据库 upsert

数据库 upsert 具有以下优点

当满足特定条件时,Prisma Client 会自动使用数据库 upsert。当不满足这些条件时,Prisma Client 会处理 upsert

要使用数据库 upsert,Prisma Client 会向数据库发送 SQL 构造 INSERT ... ON CONFLICT SET .. WHERE

数据库 upsert 前提条件

如果您的技术栈满足以下条件,Prisma Client 可以使用数据库 upsert

  • 您使用 Prisma ORM 4.6.0 或更高版本
  • 您的应用程序使用 CockroachDB、PostgreSQL 或 SQLite 数据源
数据库 upsert 查询条件

upsert 查询满足以下条件时,Prisma Client 会使用数据库 upsert

  • upsertcreateupdate 选项中没有嵌套查询
  • 查询包含使用嵌套读取的选择
  • 查询仅修改一个模型
  • upsertwhere 选项中只有一个唯一字段
  • where 选项中的唯一字段与 create 选项中的唯一字段具有相同的值

如果您的查询不满足这些条件,则 Prisma Client 会自行处理 upsert。

数据库 upsert 示例

以下示例使用此 schema

model User {
id Int @id
profileViews Int
userName String @unique
email String

@@unique([id, profileViews])
}

以下 upsert 查询满足所有条件,因此 Prisma Client 使用数据库 upsert。

prisma.user.upsert({
where: {
userName: 'Alice',
},
create: {
id: 1,
profileViews: 1,
userName: 'Alice',
email: 'alice@prisma.io',
},
update: {
email: 'updated@example.com',
},
});

在这种情况下,Prisma 使用以下 SQL 查询

INSERT INTO "public"."User" ("id","profileViews","userName","email") VALUES ($1,$2,$3,$4)
ON CONFLICT ("userName") DO UPDATE
SET "email" = $5 WHERE ("public"."User"."userName" = $6 AND 1=1) RETURNING "public"."User"."id", "public"."User"."profileViews", "public"."User"."userName", "public"."User"."email"

以下查询的 where 子句中有多个唯一值,因此 Prisma Client 使用数据库 upsert

prisma.User.upsert({
where: {
userName: 'Alice',
profileViews: 1,
id: 1,
},
create: {
id: 1,
profileViews: 1,
userName: 'Alice',
email: 'alice@prisma.io',
},
update: {
email: 'updated@example.com',
},
});

在以下查询中,wherecreate 选项中 userName 的值不同,因此 Prisma Client 使用数据库 upsert。

prisma.User.upsert({
where: {
userName: 'Alice',
},
create: {
id: 1,
profileViews: 1,
userName: 'AliceS',
email: 'alice@prisma.io',
},
update: {
email: 'updated@example.com',
},
});

在以下查询中,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: 'alice@prisma.io',
},
update: {
email: 'updated@example.com',
},
});

delete()

delete 删除现有数据库记录。您可以删除记录

  • ID
  • 唯一属性

要删除符合特定条件的记录,请使用带有过滤器的 deleteMany

选项

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

返回类型

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

备注

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

示例

删除 id1User 记录
const user = await prisma.user.delete({
where: { id: 1 },
});
删除 email 等于 else@prisma.ioUser 记录

以下查询删除特定用户记录,并使用 select 返回已删除用户的 nameemail

const deleteUser = await prisma.user.delete({
where: {
email: 'elsa@prisma.io',
},
select: {
email: true,
name: true,
},
});
显示CLI结果
{ "email": "elsa@prisma.io", "name": "Elsa" }

createMany()

createMany 在一个事务中创建多条记录。

选项

名称类型必需描述
dataEnumerable<UserCreateManyInput>将所有模型字段包装在类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。
skipDuplicates?布尔不插入具有已存在唯一字段或 ID 字段的记录。仅受支持 ON CONFLICT DO NOTHING 的数据库支持。这不包括 MongoDB 和 SQLServer

返回类型

返回类型示例描述
BatchPayload{ count: 3 }创建的记录数量。

备注

  • 自 Prisma ORM 5.12.0 版本起,SQLite 现已支持 createMany()
  • MongoDB、SQLServer 或 SQLite 不支持 skipDuplicates 选项。
  • 不能通过在顶级 createMany() 查询中使用嵌套的 createcreateManyconnectconnectOrCreate 查询来创建或连接关系。请参阅此处以获取解决方法
  • 您可以在 update()create() 查询中嵌套使用 createMany 查询 - 例如,同时添加一个 User 和两个 Post 记录,并进行嵌套的 createMany

示例

创建多个新用户
const users = await prisma.user.createMany({
data: [
{ name: 'Sonali', email: 'sonali@prisma.io' },
{ name: 'Alex', email: 'alex@prisma.io' },
],
});

createManyAndReturn()

createManyAndReturn 创建多条记录并返回结果对象。

信息

此功能在 Prisma ORM 5.14.0 及更高版本中可用,适用于 PostgreSQL、CockroachDB 和 SQLite。

选项

名称类型必需描述
dataEnumerable<UserCreateManyInput>将所有模型字段包装在类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。
selectXOR<UserSelect, null>指定要在返回对象中包含的属性
omitXOR<UserOmit, null>指定要从返回对象中排除的属性。自 5.13.0 版本起进入预览阶段。与 select 互斥。
includeXOR<UserInclude, null>指定在返回对象中应预加载哪些关系
skipDuplicates?布尔不插入具有已存在唯一字段或 ID 字段的记录。仅受支持 ON CONFLICT DO NOTHING 的数据库支持。这不包括 MongoDB 和 SQLServer

备注

  • SQLite 不支持 skipDuplicates 选项。
  • 请注意,createManyAndReturn 返回的元素顺序不保证。
  • 不能通过在顶级 createManyAndReturn() 查询中嵌套使用 createcreateManyconnectconnectOrCreate 查询来创建或连接关系。请参阅此处以获取解决方法
  • 当关系通过 include 包含时,会为每个关系生成一个单独的查询。
  • 不支持 relationLoadStrategy: join

返回类型

返回类型示例描述
JavaScript 数组对象(有类型)User[]
JavaScript 数组对象(纯文本)[{ name: "Sonali" }]使用 selectomitinclude 确定要返回的字段。

示例

创建并返回多个新用户
const users = await prisma.user.createManyAndReturn({
data: [
{ name: 'Sonali', email: 'sonali@prisma.io' },
{ name: 'Alex', email: 'alex@prisma.io' },
],
})
显示CLI结果
[
{ "id": 0, "name": "Sonali", "email": "sonali@prisma.io", "profileViews": 0 },
{ "id": 1, "name": "Alex", "email": "alex@prisma.io", "profileViews": 0 }
]

updateMany()

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

选项

名称类型必需描述
dataXOR<UserUpdateManyMutationInput,
UserUncheckedUpdateManyInput>
将模型的所有字段包装在类型中,以便在更新现有记录时提供它们。在数据模型中标记为可选或具有默认值的字段在 data 上是可选的。
whereUserWhereInput将模型的所有字段包装在类型中,以便可以通过任何属性过滤列表。如果您不过滤列表,则所有记录都将被更新。
限制数字限制更新的记录数量。

返回类型

返回类型示例描述
BatchPayload{ count: 4 }已更新记录的数量。
export type BatchPayload = {
count: number;
};

示例

将所有 nameAliceUser 记录更新为 ALICE
const updatedUserCount = await prisma.user.updateMany({
where: { name: 'Alice' },
data: { name: 'ALICE' },
});
更新所有 email 包含 prisma.io 且至少一篇相关 Post 点赞数超过 10 的 User 记录
const updatedUserCount = await prisma.user.updateMany({
where: {
email: {
contains: 'prisma.io',
},
posts: {
some: {
likes: {
gt: 10,
},
},
},
},
data: {
role: 'USER',
},
});
更新 email 包含 prisma.ioUser 记录,但限制更新 5 条记录。
const updatedUserCount = await prisma.user.updateMany({
where: {
email: {
contains: 'prisma.io',
},
},
data: {
role: 'USER',
},
limit: 5,
});

updateManyAndReturn()

信息

此功能在 Prisma ORM 6.2.0 及更高版本中可用,适用于 PostgreSQL、CockroachDB 和 SQLite。

updateManyAndReturn 更新多条记录并返回结果对象。

选项

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

返回类型

返回类型示例描述
JavaScript 数组对象(有类型)User[]
JavaScript 数组对象(纯文本)[{ name: "Sonali" }]使用 selectomitinclude 确定要返回的字段。

示例

更新并返回多个用户
const users = await prisma.user.updateManyAndReturn({
where: {
email: {
contains: 'prisma.io',
}
},
data: {
role: 'ADMIN'
},
})
显示CLI结果
[
{ "id": 0, "name": "Sonali", "email": "sonali@prisma.io", "role": "ADMIN", "profileViews": 0 },
{ "id": 1, "name": "Alex", "email": "alex@prisma.io", "role": "ADMIN", "profileViews": 0 }
]

deleteMany()

deleteMany 在一个事务中删除多条记录。

选项

名称类型必需描述
whereUserWhereInput将模型的所有字段包装在类型中,以便可以通过任何字段进行筛选。
限制整数限制删除的记录数量。

返回类型

返回类型示例描述
BatchPayload{ count: 4 }已删除记录的数量。
export type BatchPayload = {
count: number;
};

示例

删除所有 User 记录
const deletedUserCount = await prisma.user.deleteMany({});
删除所有 nameAliceUser 记录
const deletedUserCount = await prisma.user.deleteMany({
where: { name: 'Alice' },
});
删除所有 email 包含 prisma.ioUser 记录,但限制删除 5 条记录。
const deletedUserCount = await prisma.user.deleteMany({
where: {
email: {
contains: 'prisma.io',
},
},
limit: 5,
});

请参阅筛选条件和运算符,了解如何筛选要删除的记录的示例。

count()

选项

名称类型必需描述
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性筛选列表。
orderByXOR<Enumerable<PostOrder
ByInput>, PostOrderByInput>
允许您按任何属性对返回列表进行排序。
游标UserWhereUniqueInput指定列表的位置(值通常指定 id 或其他唯一值)。
take数字指定列表中应返回的对象数量(从列表的开始(正值)或结束(负值)从指定的 cursor 位置开始计算)
跳过数字指定列表中应跳过的返回对象数量。

返回类型

返回类型示例描述
数字29记录的数量。
UserCountAggregateOutputType{ _all: 27, name: 10 }如果使用了 select 则返回。

示例

统计所有 User 记录
const result = await prisma.user.count();
统计所有至少有一篇已发布 PostUser 记录
const result = await prisma.user.count({
where: {
post: {
some: {
published: true,
},
},
},
});
使用 select 执行三个独立的计数

以下查询返回

  • 所有记录的数量 (_all)
  • 所有 name 字段非 null 的记录的数量
  • 所有 city 字段非 null 的记录的数量
const c = await prisma.user.count({
select: {
_all: true,
city: true,
name: true,
},
});

aggregate()

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

选项

名称类型必需描述
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性筛选列表。
orderByXOR<Enumerable<UserOrderByInput>,
UserOrderByInput>
允许您按任何属性对返回列表进行排序。
游标UserWhereUniqueInput指定列表的位置(值通常指定 id 或其他唯一值)。
take数字指定列表中应返回的对象数量(从列表的开始(正值)或结束(负值)从指定的 cursor 位置开始计算)
跳过数字指定列表中应跳过的返回对象数量。
_count返回匹配记录或非 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 的组。
take数字指定列表中应返回的对象数量(从列表的开始(正值)或结束(负值)从指定的 cursor 位置开始计算)
跳过数字指定列表中应跳过的返回对象数量。
_counttrue | UserCountAggregateInputType返回匹配记录或非 null 字段的计数。
_avgUserAvgAggregateInputType返回指定字段所有值的平均值。
_sumUserSumAggregateInputType返回指定字段所有值的总和。
_minUserMinAggregateInputType返回指定字段的最小可用值。
_maxUserMaxAggregateInputType返回指定字段的最大可用值。

示例

country/city 分组,其中平均 profileViews 大于 200,并返回每个组的 profileViews_sum

该查询还返回每个组中 _all 记录的计数,以及每个组中 city 字段值非 null 的所有记录。

const groupUsers = await prisma.user.groupBy({
by: ['country', 'city'],
_count: {
_all: true,
city: true,
},
_sum: {
profileViews: true,
},
orderBy: {
country: 'desc',
},
having: {
profileViews: {
_avg: {
gt: 200,
},
},
},
});
显示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())

aggregateRaw()

参见:使用原始 SQL (aggregateRaw())

模型查询选项

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结果
select 中的 include
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: 'alice@prisma.io',
posts: {
create: [{ title: 'This is my first post' }, { title: 'Here comes a second post' }],
},
},
include: { posts: true }, // Returns all fields for all posts
});

include 的生成类型

以下示例演示了如何将 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 返回的对象中排除哪些字段。

备注

  • 您不能同时使用 omitselect,因为它们的目的相反
  • omit 随 Prisma ORM 6.2.0 发布到通用版本。在 Prisma ORM 5.13.06.1.0 版本中,它通过 omitApi 预览功能提供。

示例

从所有 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 schema 文件中通过 relationJoins 预览功能标志启用它

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

添加此标志后,您需要再次运行 prisma generate 以重新生成 Prisma Client。relationJoins 功能目前在 PostgreSQL、CockroachDB 和 MySQL 上可用。

备注

  • 在大多数情况下,默认的 join 策略会更有效。如果您想节省数据库服务器上的资源,或者如果您的性能分析显示应用程序级连接性能更好,请使用 query
  • 您只能在查询的顶层指定 relationLoadStrategy。顶层选择将影响所有嵌套的子查询。

示例

使用 include 时,通过数据库级别 JOIN 加载 posts 关系
const users = await prisma.user.findMany({
relationLoadStrategy: 'join',
include: {
posts: true,
},
});
使用 select 时,通过数据库级别 JOIN 加载 posts 关系
const users = await prisma.user.findMany({
relationLoadStrategy: 'join',
select: {
posts: true,
},
});

where

where 定义一个或多个过滤器,可用于筛选记录属性(如用户的电子邮件地址)或相关记录属性(如用户最近 10 篇最热门帖子标题)。

示例

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

where 的生成类型

以下示例演示了如何将 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: 'rich@boop.com',
    },
    },
    ],
    });
  • UserWhereUniqueInput 此类型通过公开模型上的任何唯一字段来工作。被指定为 @id 的字段被认为是唯一的,被指定为 @unique 的字段也是如此。

    从 4.5.0 版本开始,此类型公开模型上的所有字段。这意味着当您根据唯一字段筛选单个记录时,您可以同时检查额外的非唯一字段和唯一字段。 了解更多

    // UserWhereUniqueInput
    const whereEmailIsUnique = Prisma.validator<Prisma.UserWhereUniqueInput>()({
    email: 'rich@boop.com',
    })
  • PostScalarWhereInput

    const whereScalarTitleIs = Prisma.validator<Prisma.PostScalarWhereInput>()({
    title: 'boop',
    });
  • PostUpdateWithWhereUniqueWithoutAuthorInput - 此类型接受一个唯一的 where 字段(一个 @id 或另一个指定的 @unique),并更新 Post 模型上除 Author 之外的任何字段。AuthorPost 模型上的标量字段。

    const updatePostByIdWithoutAuthor =
    Prisma.validator<Prisma.PostUpdateWithWhereUniqueWithoutAuthorInput>()({
    where: {
    id: 1,
    },
    data: {
    content: 'This is some updated content',
    published: true,
    title: 'This is a new title',
    },
    });
  • PostUpsertWithWhereUniqueWithoutAuthorInput - 此类型将更新 Post 记录的标题字段,其中 id 匹配,如果不存在则会创建它。

    const updatePostTitleOrCreateIfNotExist =
    Prisma.validator<Prisma.PostUpsertWithWhereUniqueWithoutAuthorInput>()({
    where: {
    id: 1,
    },
    update: {
    title: 'This is a new title',
    },
    create: {
    id: 1,
    title: 'If the title doesnt exist, then create one with this text',
    },
    });
  • PostUpdateManyWithWhereWithoutAuthorInput - 此类型将更新所有 Post 记录,其中 published 设置为 false。

    const publishAllPosts = Prisma.validator<Prisma.PostUpdateManyWithWhereWithoutAuthorInput>()({
    where: {
    published: {
    equals: false,
    },
    },
    data: {
    published: true,
    },
    });

orderBy

对记录列表进行排序。另请参阅:排序

备注

sort 参数的输入

名称描述
asc升序排序(A → Z)
desc降序排序(Z → A)

nulls 参数的输入

注意

  • 此参数是可选的。
  • 它仅用于可选的标量字段。如果您尝试在必填或关联字段上按 null 值排序,Prisma Client 将抛出 P2009 错误
  • 此功能在 4.1.0 及更高版本中可用,作为预览功能。有关如何启用此功能的详细信息,请参阅将 null 值排在最前或最后
名称描述
firstnull 值排在最前。
lastnull 值排在最后。

示例

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 排序 Postnull 记录优先

以下查询按用户姓名排序帖子,null 记录优先

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

按标题相关性排序 Post

信息

对于 PostgreSQL,此功能仍处于预览阶段。要使用它,请启用 fullTextSearchPostgres 功能标志

以下查询按搜索词 'database' 与标题的相关性对帖子进行排序

const posts = await prisma.post.findMany({
orderBy: {
_relevance: {
fields: ['title'],
search: 'database',
sort: 'asc'
},
})

posts 数量排序 User

以下查询按帖子数量排序用户

const getActiveusers = await prisma.user.findMany({
orderBy: {
posts: {
count: 'desc',
},
},
});
按多个字段排序 User - email role

以下示例按两个字段排序用户 - 首先是 email,然后是 role

const users = await prisma.user.findMany({
select: {
email: true,
role: true,
},
orderBy: [
{
email: 'desc',
},
{
role: 'desc',
},
],
});
显示CLI结果

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

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

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

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

以下示例通过 ID 检索单个 User 记录,以及按 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结果

nativeDistinct

在您的 Prisma schema 中启用 nativeDistinct 会将 distinct 操作推送到数据库层(如果支持)。这可以显著提高性能。但是,请注意

  • 某些数据库可能不完全支持特定字段组合上的 DISTINCT。
  • 不同提供商的行为可能有所不同。

要启用 nativeDistinct

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

有关详细信息,请参阅预览功能

嵌套查询

create

嵌套 create 查询会将一条或一组新的相关记录添加到父记录。请参阅:处理关系

备注

  • 当您 create() (prisma.user.create(...)) 一个新的父记录或 update() (prisma.user.update(...)) 一个现有父记录时,create 可作为嵌套查询使用。
  • 您可以使用嵌套的 create 嵌套的 createMany 来创建多个相关记录。如果需要 skipDuplicates 查询选项,您应该使用 createMany

示例

创建包含新 Profile 记录的新 User 记录
const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
profile: {
create: { bio: 'Hello World' },
},
},
});
创建包含新 User 记录的新 Profile 记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
create: { email: 'alice@prisma.io' },
},
},
})
创建包含新 Post 记录的新 User 记录
const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
posts: {
create: { title: 'Hello World' },
},
},
});
创建包含两条新 Post 记录的新 User 记录

因为这是一对多关系,您还可以通过向 create 传递一个数组来一次性创建多个 Post 记录

const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
posts: {
create: [
{
title: 'This is my first post',
},
{
title: 'Here comes a second post',
},
],
},
},
});

注意:您也可以使用嵌套的 createMany 来实现相同的结果。

通过创建新的 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
create: { bio: 'Hello World' },
},
},
});
通过创建新的 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
create: { title: 'Hello World' },
},
},
})

createMany

嵌套 createMany 查询会将一组新的记录添加到父记录。请参阅:处理关系

备注

  • 当您 create() (prisma.user.create(...)) 一个新的父记录或 update() (prisma.user.update(...)) 一个现有父记录时,createMany 可作为嵌套查询使用。
    • 在一对多关系的上下文中可用 — 例如,您可以 prisma.user.create(...) 一个用户并使用嵌套的 createMany 来创建多个帖子(帖子有一个用户)。
    • 在多对多关系的上下文中不可用 — 例如,您不能 prisma.post.create(...) 一个帖子并使用嵌套的 createMany 来创建类别(许多帖子有许多类别)。
  • 您不能再嵌套一个 createcreateMany
  • 允许直接设置外键 — 例如,设置帖子的 categoryId
  • 从 Prisma ORM 5.12.0 版本开始,SQLite 支持嵌套的 createMany
  • 您可以使用嵌套的 create 嵌套的 createMany 来创建多个相关记录 - 如果您不需要 skipDuplicates 查询选项,您可能应该使用 create

选项

名称类型必需描述
dataEnumerable<UserCreateManyInput>将所有模型字段包装在类型中,以便在创建新记录时提供它们。在数据模型中标记为可选或具有默认值的字段是可选的。
skipDuplicates?布尔不插入具有已存在唯一字段或 ID 字段的记录。仅受支持 ON CONFLICT DO NOTHING 的数据库支持。这不包括 MongoDB 和 SQLServer

示例

更新 User 和多个新的相关 Post 记录
const user = await prisma.user.update({
where: {
id: 9,
},
data: {
name: 'Elliott',
posts: {
createMany: {
data: [{ title: 'My first post' }, { title: 'My second post' }],
},
},
},
});

set

set 覆盖关系的当前值 — 例如,用不同的列表替换 Post 记录列表。请参阅:处理关系

示例

通过断开任何先前的 Post 记录并连接两条其他现有记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
set: [{ id: 32 }, { id: 42 }],
},
},
});

connect

嵌套 connect 查询通过指定 ID 或唯一标识符将记录连接到现有相关记录。请参阅:处理关系

备注

  • 当您创建新的父记录或更新现有父记录时,connect 可作为嵌套查询使用。

  • 如果相关记录不存在,Prisma Client 将抛出异常

    The required connected records were not found. Expected 1 records to be connected, found 0.
  • 当同时使用 setconnect 时,它们的应用顺序会显著影响结果。如果在 connect 之前使用 set,则连接的记录将只反映 connect 操作建立的最终状态,因为 set 会在 connect 建立新连接之前清除所有现有连接。反之,如果在 set 之前应用 connect,则 set 操作将通过清除所有已连接的记录并将其替换为自身指定的状态来覆盖 connect 操作。

示例

创建新的 Profile 记录并通过唯一字段将其连接到现有 User 记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
connect: { email: 'alice@prisma.io' },
},
},
});
创建新的 Profile 记录并通过 ID 字段将其连接到现有 User 记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
connect: { id: 42 }, // sets userId of Profile record
},
},
});

2.11.0 及更高版本中,您可以直接设置外键

const user = await prisma.profile.create({
data: {
bio: 'Hello World',
userId: 42,
},
});

但是,您不能在同一查询中同时使用直接方法和 connect 方法。有关详细信息,请参阅此问题评论

创建新的 Post 记录并将其连接到现有 User 记录
const user = await prisma.post.create({
data: {
title: 'Hello World',
author: {
connect: { email: 'alice@prisma.io' },
},
},
});
通过连接到现有 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
connect: { id: 24 },
},
},
});
通过连接到两条现有 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
connect: [{ id: 24 }, { id: 42 }],
},
},
});

connectOrCreate

connectOrCreate 要么 通过 ID 或唯一标识符将记录连接到现有相关记录,要么 在记录不存在时创建新的相关记录。请参阅:处理关系

备注

  • 同时运行的多个 connectOrCreate 查询(作为并发事务)可能导致竞态条件。考虑以下示例,其中两个查询试图同时 connectOrCreate 名为 computing 的博客文章标签(标签名称必须是唯一的)

    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. 尝试将 profile 连接到电子邮件地址为 alice@prisma.ioUser
  3. 如果匹配的用户不存在,则创建一个新用户
const user = await prisma.profile.create({
data: {
bio: 'The coolest Alice on the planet',
user: {
connectOrCreate: {
where: { email: 'alice@prisma.io' },
create: { email: 'alice@prisma.io'}
},
},
})
创建新的 Post 记录并将其连接到现有 User 记录,创建新的 User
const user = await prisma.post.create({
data: {
title: 'Hello World',
author: {
connectOrCreate: {
where: { email: 'alice@prisma.io' },
create: { email: 'alice@prisma.io' },
},
},
},
});
通过连接到现有 Profile 记录创建新的 Profile 记录来更新现有 User 记录

以下示例

  1. 尝试将用户连接到 id20Profile
  2. 如果匹配的 profile 不存在,则创建一个新 profile
const updateUser = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
connectOrCreate: {
where: { id: 20 },
create: {
bio: 'The coolest Alice in town',
},
},
},
},
});
通过连接到两条现有 Post 记录或创建两条新 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
connectOrCreate: [
{
where: { id: 32 },
create: { title: 'This is my first post' },
},
{
where: { id: 19 },
create: { title: 'This is my second post' },
},
],
},
},
});

disconnect

嵌套 disconnect 查询会中断父记录和相关记录之间的连接,但不会删除任何记录。请参阅:处理关系

备注

  • disconnect 仅在关系是可选时可用。

  • 如果您尝试断开的关系不存在

    • 在 2.21.0 及更高版本中),该操作不做任何事情

    • (在 2.21.0 之前)如果提供的 ID 或唯一标识符未连接,Prisma Client 将抛出异常

      The records for relation `PostToUser` between the `User` and `Post` models are not connected.

示例

通过断开与 Profile 记录的连接来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'bob@prisma.io' },
data: {
profile: {
disconnect: true,
},
},
});
通过断开与两条 Post 记录的连接来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
disconnect: [{ id: 44 }, { id: 46 }],
},
},
});

update

嵌套的 update 查询会更新一个或多个相关记录,其中父记录的 ID 为 n。请参阅:处理关系

备注

  • 嵌套的 update 查询仅在顶级 update 查询的上下文中可用(例如,prisma.user.update(...))。

  • 如果父记录不存在,Prisma Client 将抛出异常

    AssertionError("Expected a valid parent ID to be present for nested update to-one case.")
  • 如果您想要更新的相关记录不存在,Prisma Client 将抛出异常

    AssertionError("Expected a valid parent ID to be present for nested update to-one case.")

示例

通过更新所连接的 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
update: { bio: 'Hello World' },
},
},
});
通过更新所连接的两条 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
update: [
{
data: { published: true },
where: { id: 32 },
},
{
data: { published: true },
where: { id: 23 },
},
],
},
},
});

upsert

信息

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

嵌套的 upsert 查询会在相关记录存在时更新它,或者在不存在时创建新的相关记录。

示例

通过更新现有 User 记录所连接的 Profile 记录或创建新记录来更新现有 User 记录(upsert
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
upsert: {
create: { bio: 'Hello World' },
update: { bio: 'Hello World' },
},
},
},
});
通过更新现有 User 记录所连接的两个 Post 记录或创建新记录来更新现有 User 记录(upsert
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
upsert: [
{
create: { title: 'This is my first post' },
update: { title: 'This is my first post' },
where: { id: 32 },
},
{
create: { title: 'This is my second post' },
update: { title: 'This is my second post' },
where: { id: 23 },
},
],
},
},
});

delete

嵌套的 delete 查询会删除相关记录。父记录不会被删除。

备注

  • delete 仅在关系可选时可用。

示例

通过删除现有 User 记录所连接的 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
delete: true,
},
},
});
通过删除现有 User 记录所连接的两个 Post 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
posts: {
delete: [{ id: 34 }, { id: 36 }],
},
},
});

updateMany

嵌套的 updateMany 会更新相关记录列表并支持筛选——例如,您可以更新用户的未发布帖子。

示例

更新属于特定用户的所有未发布帖子
const result = await prisma.user.update({
where: {
id: 2,
},
data: {
posts: {
updateMany: {
where: {
published: false,
},
data: {
likes: 0,
},
},
},
},
});

deleteMany

嵌套的 deleteMany 会删除相关记录并支持筛选。例如,您可以在更新该用户的其他属性时删除该用户的帖子。

示例

作为更新的一部分,删除属于特定用户的所有帖子
const result = await prisma.user.update({
where: {
id: 2,
},
data: {
name: 'Updated name',
posts: {
deleteMany: {},
},
},
});

筛选条件和运算符

equals

值等于 n

示例

返回所有 name 等于 "Eleanor" 的用户

const result = await prisma.user.findMany({
where: {
name: {
equals: 'Eleanor',
},
},
});

您也可以省略 equals

const result = await prisma.user.findMany({
where: {
name: 'Eleanor',
},
});

返回所有数量低于“警告数量”阈值的产品

此示例比较了同一模型的字段,该功能从版本 4.3.0 开始可用。

const productsWithLowQuantity = await prisma.product.findMany({
where: {
quantity: {
lte: prisma.product.fields.warnQuantity
},
},
});

返回所有收藏颜色为蓝色和绿色的用户

此示例查找将其 favoriteColors 字段设置为 ['blue', 'green'] 的用户。

请注意,当使用 equals 时,元素的顺序很重要。也就是说 ['blue', 'green'] 等于 ['green', 'blue']

const favoriteColorFriends = await prisma.user.findMany({
where: {
favoriteColors: {
equals: ['blue', 'green'],
},
},
});

not

值不等于 n

示例

返回所有 name 等于 "Eleanor" 的用户
const result = await prisma.user.findMany({
where: {
name: {
not: 'Eleanor',
},
},
});
警告

not 将返回所有不匹配给定值的项目。但是,如果列可为空,则不会返回 NULL 值。如果您需要返回 null 值,请使用 OR 运算符以包含 NULL 值。

返回所有 name 等于 "Eleanor" 的用户,包括 nameNULL 的用户
await prisma.user.findMany({
where: {
OR: [
{ name: { not: 'Eleanor' } },
{ name: null }
]
}
})

in

n 存在于列表中。

注意

null 值不会被返回。例如,如果您组合使用 inNOT 来返回名称不在列表中的用户,则不会返回名称为 null 值的用户。

示例

获取 id 可以在以下列表中找到的 User 记录:[22, 91, 14, 2, 5]
const getUser = await prisma.user.findMany({
where: {
id: { in: [22, 91, 14, 2, 5] },
},
});
获取 name 可以在以下列表中找到的 User 记录:['Saqui', 'Clementine', 'Bob']
const getUser = await prisma.user.findMany({
where: {
name: { in: ['Saqui', 'Clementine', 'Bob'] },
},
});
获取 name 不在列表中的 User 记录

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

const getUser = await prisma.user.findMany({
where: {
NOT: {
name: { in: ['Saqui', 'Clementine', 'Bob'] },
},
},
});
获取至少一个 Post 包含至少一个指定 CategoryUser 记录
const getUser = await prisma.user.findMany({
where: {
// Find users where..
posts: {
some: {
// ..at least one (some) posts..
categories: {
some: {
// .. have at least one category ..
name: {
in: ['Food', 'Introductions'], // .. with a name that matches one of the following.
},
},
},
},
},
},
});

notIn

n 不存在于列表中。

备注

  • null 值不会被返回。

示例

获取 id 在以下列表中的 User 记录:[22, 91, 14, 2, 5]
const getUser = await prisma.user.findMany({
where: {
id: { notIn: [22, 91, 14, 2, 5] },
},
});

lt

n 小于 x

示例

获取所有 likes 小于 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 字段中进行搜索。

信息

对于 PostgreSQL,此功能仍处于预览阶段。要使用它,请启用 fullTextSearchPostgres 功能标志

示例

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

startsWith

示例

获取所有 titlePr 开头(例如 Prisma)的 Post 记录
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 不包含 SQLPost 记录
const result = await prisma.post.findMany({
where: {
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 来返回所有至少有一个关系的记录

示例

获取所有 User 记录,其中一些帖子提到了 Prisma
const result = await prisma.user.findMany({
where: {
post: {
some: {
content: {
contains: "Prisma"
}
}
}
}
}

every

返回所有所有(“every”)相关记录匹配筛选条件的记录。

示例

获取所有 User 记录,其中所有帖子都已发布
const result = await prisma.user.findMany({
where: {
post: {
every: {
published: true
},
}
}
}

none

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

备注

示例

获取所有零帖子的 User 记录
const result = await prisma.user.findMany({
where: {
post: {
none: {} // User has no posts
}
}
}
获取所有零已发布帖子的 User 记录
const result = await prisma.user.findMany({
where: {
post: {
none: {
published: true
}
}
}
}

is

返回所有相关记录匹配筛选条件的记录(例如,用户的名称 is Bob)。

示例

获取所有用户名为 "Bob"Post 记录
const result = await prisma.post.findMany({
where: {
user: {
is: {
name: "Bob"
},
}
}
}

isNot

返回所有相关记录不匹配筛选条件的记录(例如,用户的名称 isNot Bob)。

示例

获取所有用户名不是 "Bob"Post 记录
const result = await prisma.post.findMany({
where: {
user: {
isNot: {
name: "Bob"
},
}
}
}

标量列表方法

set

使用 set 覆盖标量列表字段的值。

备注

  • set 是可选的——您可以直接设置值

    tags: ['computers', 'books'];

示例

tags 的值设置为字符串值列表
const setTags = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
set: ['computing', 'books'],
},
},
});
tags 设置为值列表,使用 set 关键字
const setTags = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: ['computing', 'books'],
},
});

tags 的值设置为单个字符串值

const setTags = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
set: 'computing',
},
},
});

push

push 在版本 2.20.0 及更高版本中可用。使用 push一个值或多个值添加到标量列表字段中。

备注

  • 仅适用于 PostgreSQL 和 MongoDB。
  • 您可以推送一个值列表或单个值。

示例

tags 列表中添加一个 computing
const addTag = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
push: 'computing',
},
},
});
const addTag = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
push: ['computing', 'genetics'],
},
},
});

unset

警告

此方法仅在 MongoDB 版本的 3.11.1 及更高版本中可用。

使用 unset 来取消设置标量列表的值。与 set: null 不同,unset 会完全删除该列表。

示例

取消设置 tags 的值
const setTags = await prisma.post.update({
where: {
id: 9,
},
data: {
tags: {
unset: true,
},
},
});

标量列表筛选器

标量列表筛选器允许您按列表/数组字段的内容进行筛选。

警告

适用于

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

备注

  • 标量列表/数组筛选器忽略 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

警告

此筛选器仅在 MongoDB 版本的 3.11.1 及更高版本中可用。

筛选列表以仅包含已设置(设置为值或显式设置为 null)的结果。将此筛选器设置为 true 将排除根本未设置的未定义结果。

示例

以下查询返回所有 tags 已设置为 null 或值的 Post 记录

const posts = await prisma.post.findMany({
where: {
tags: {
isSet: true,
},
},
});

equals

列表精确匹配给定值。

示例

以下查询返回所有 tags 列表仅包含 "databases""typescript"Post 记录

const posts = await prisma.post.findMany({
where: {
tags: {
equals: ['databases', 'typescript'],
},
},
});

复合类型方法

警告

仅在 Prisma 3.10.0 及更高版本中适用于 MongoDB。

复合类型方法允许您创建、更新和删除复合类型

set

使用 set 覆盖复合类型的值。

备注

  • set 关键字是可选的——您可以直接设置值
    photos: [
    { height: 100, width: 200, url: '1.jpg' },
    { height: 100, width: 200, url: '2.jpg' },
    ];

示例

在新 order 中设置 shippingAddress 复合类型
const order = await prisma.order.create({
data: {
// Normal relation
product: { connect: { id: 'some-object-id' } },
color: 'Red',
size: 'Large',
// Composite type
shippingAddress: {
set: {
street: '1084 Candycane Lane',
city: 'Silverlake',
zip: '84323',
},
},
},
});
将可选复合类型设置为 null
const order = await prisma.order.create({
data: {
// Embedded optional type, set to null
billingAddress: {
set: null,
},
},
});

unset

使用 unset 来取消设置复合类型的值。与 set: null 不同,这会从 MongoDB 文档中完全删除该字段。

示例

order 中删除 billingAddress
const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
billingAddress: {
// Unset the billing address
// Removes "billingAddress" field from order
unset: true,
},
},
});

update

使用 update 更新必需复合类型中的字段。

备注

update 方法不能用于可选类型。请改用 upsert

示例

更新 shippingAddress 复合类型的邮政编码字段
const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
shippingAddress: {
// Update just the zip field
update: {
zip: '41232',
},
},
},
});

upsert

使用 upsert 更新现有可选复合类型(如果存在),否则设置复合类型。

备注

upsert 方法不能用于必需类型。请改用 update

示例

如果不存在,则创建新的 billingAddress,否则更新它
const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
billingAddress: {
// Create the address if it doesn't exist,
// otherwise update it
upsert: {
set: {
street: '1084 Candycane Lane',
city: 'Silverlake',
zip: '84323',
},
update: {
zip: '84323',
},
},
},
},
});

push

使用 push 将值推送到复合类型列表的末尾。

示例

将新照片添加到 photos 列表
const product = prisma.product.update({
where: {
id: 10,
},
data: {
photos: {
// Push a photo to the end of the photos list
push: [{ height: 100, width: 200, url: '1.jpg' }],
},
},
});

复合类型筛选器

警告

仅在 Prisma 3.11.0 及更高版本中适用于 MongoDB。

复合类型筛选器允许您筛选复合类型的内容。

equals

使用 equals 通过匹配复合类型或复合类型列表来筛选结果。要求复合类型的所有必需字段都匹配。

备注

当匹配可选字段时,您需要区分文档中未定义的(缺失的)字段和已显式设置为 null 的字段

  • 如果您省略可选字段,它将匹配未定义的字段,但不会匹配已设置为 null 的字段
  • 如果您使用 equals: { ... exampleField: null ... } 筛选可选字段的 null 值,那么它将仅匹配该字段已设置为 null 的文档,而不匹配未定义的字段

使用 equals 时,字段和列表的顺序很重要

  • 对于字段,{ "a": "1", "b": "2" }{ "b": "2", "a": "1" } 不被视为相等
  • 对于列表,[ { "a": 1 }, { "a": 2 } ][ { "a": 2 }, { "a": 1 } ] 不被视为相等

示例

查找与给定 shippingAddress 完全匹配的订单
const orders = await prisma.order.findMany({
where: {
shippingAddress: {
equals: {
street: '555 Candy Cane Lane',
city: 'Wonderland',
zip: '52337',
},
},
},
});
查找照片与所有给定 url 列表匹配的产品
const product = prisma.product.findMany({
where: {
equals: {
photos: [{ url: '1.jpg' }, { url: '2.jpg' }],
},
},
});

is

使用 is 通过匹配复合类型中的特定字段来筛选结果。

示例

查找 shippingAddress 匹配给定街道名称的订单
const orders = await prisma.order.findMany({
where: {
shippingAddress: {
is: {
street: '555 Candy Cane Lane',
},
},
},
});

isNot

使用 isNot 筛选复合类型字段不匹配的结果。

示例

查找 shippingAddress 不匹配给定邮政编码的订单
const orders = await prisma.order.findMany({
where: {
shippingAddress: {
isNot: {
zip: '52337',
},
},
},
});

isEmpty

使用 isEmpty 筛选复合类型的空列表结果。

示例

查找没有照片的产品
const product = prisma.product.findMany({
where: {
photos: {
isEmpty: true,
},
},
});

every

使用 every 筛选复合类型列表,其中列表中的每个项目都匹配条件

示例

查找第一款所有照片高度都为 200 的产品
const product = await prisma.product.findFirst({
where: {
photos: {
every: {
height: 200,
}
}
},
})

some

使用 some 筛选复合类型列表,其中列表中一个或多个项目匹配条件。

示例

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

none

使用 none 筛选复合类型列表,其中列表中没有项目匹配条件。

示例

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

原子数字运算

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

概述:竞态条件

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

客户端操作
客户端 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',
},
},
});

mode

指定字符串筛选是否应区分大小写(默认)或不区分大小写。

以下查询返回所有嵌套 favorites > catBreed 键值包含 "Van""van" 的用户

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

array_contains

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

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

注意:在 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,则会填充此项。
model模型类型——例如,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 预览功能提供。

信息

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

  • 如果您的版本早于 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 } },
});
信息

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: "bob@prisma.io" }, { email: "alice@prisma.io" }] },
// ^^^ Valid: the expression specifies a unique field (`id`) outside of any boolean operators
data: { ... }
})

// SQL equivalent:
// WHERE id = 1 AND (email = "bob@prisma.io" OR email = "alice@prisma.io")

以下示例无效,因为没有任何布尔运算符之外的唯一字段

await prisma.user.update({
where: { OR: [{ email: "bob@prisma.io" }, { email: "alice@prisma.io" }] },
// ^^^ Invalid: the expressions does not contain a unique field outside of boolean operators
data: { ... }
})

一对一关系

从 4.5.0 版本开始,您可以在一对一关系的以下操作中筛选非唯一字段

  • 嵌套更新
  • 嵌套插入或更新 (upsert)
  • 嵌套断开连接
  • 嵌套删除

Prisma Client 会自动使用唯一过滤器来选择适当的相关记录。因此,您不需要在 where 语句中通过 WhereUniqueInput 生成的类型指定唯一过滤器。相反,where 语句具有 WhereInput 生成的类型。您可以使用此类型进行过滤,而不受 WhereUniqueInput 的限制。

嵌套更新示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
// Before Prisma version 4.5.0
update: { field: "updated" }
// From Prisma version 4.5.0, you can also do the following:
update: { where: { /*WhereInput*/ }, data: { field: "updated" } } }
}
}
})
嵌套插入或更新 (upsert) 示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
upsert: {
where: { /* WhereInput */ } // new argument from Prisma 4.5.0
create: { /* CreateInput */ },
update: { /* CreateInput */ },
}
}
}
})
嵌套断开连接示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
// Before Prisma version 4.5.0
disconnect: true
// From Prisma version 4.5.0, you can also do the following:
disconnect: { /* WhereInput */ }
}
}
})
嵌套删除示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
// Before Prisma version 4.5.0
delete: true
// From Prisma version 4.5.0, you can also do the following:
delete: { /* WhereInput */ }
}
}
})

PrismaPromise 行为

所有 Prisma Client 查询都返回 PrismaPromise 的实例。这是一个“thenable”,这意味着 PrismaPromise 仅在您调用 await.then().catch() 时才执行。此行为与常规 JavaScript Promise 不同,后者会立即开始执行。

例如

const findPostOperation = prisma.post.findMany({}); // Query not yet executed

findPostOperation.then(); // Prisma Client now executes the query
// or
await findPostOperation; // Prisma Client now executes the query

使用 $transaction API 时,此行为使 Prisma Client 能够将所有查询作为一个事务传递给查询引擎。

© . All rights reserved.