跳到主要内容

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" }]
日志级别
名称示例
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 Started http server on http://127.0.0.1:58471
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结果
info, warnerror 事件记录到控制台
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 返回错误的级别和格式。

错误格式

名称描述
undefined如果未定义,默认为无颜色。
pretty启用漂亮错误格式化。
colorless (默认)启用无颜色错误格式化。
minimal启用极简错误格式化。

示例

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

adapter

定义一个驱动适配器实例。另请参阅数据库驱动程序

信息

此功能从版本 5.4.0 及更高版本开始可用,需要启用 driverAdapters 功能标志。

示例

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

import { 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

备注

选项

选项描述
RejectOnNotFound全局启用 (true / false) 抛出自定义错误。
RejectPerOperation按操作启用 (true / false) 按操作、按模型抛出自定义错误。

示例

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

transactionOptions

信息

注意transactionOptions 在 v5.10.0 中引入。

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

备注

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

选项

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

注意:最佳实践是在将任何不受信任的用户数据传递给 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 起在预览中。
relationLoadStrategy'join''query'默认:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用时可用。自 5.9.0 起在预览中。

返回类型

返回类型示例描述
JavaScript 对象(类型化)User
JavaScript 对象(普通){ title: "Hello world" }使用 selectinclude 来确定返回哪些字段。
nullnull未找到记录

示例

获取 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 起在预览中。
relationLoadStrategy'join''query'默认:join。指定关联查询的加载策略。仅与 include(或关联字段上的 select)结合使用时可用。自 5.9.0 起在预览中。
whereUserWhereInput所有 模型字段包装在类型中,以便列表可以通过任何属性进行过滤。
orderByXOR<Enumerable<UserOrderByInput>, UserOrderByInput>允许您按任何属性对返回的列表进行排序。

返回类型

返回类型示例描述
JavaScript 对象(类型化)User指定返回对象中包含哪些属性。
JavaScript 对象(普通){ title: "Hello world" }使用 selectinclude 来确定返回哪些字段。
nullnull未找到记录

备注

  • 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 起在预览中。
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 创建一个新的数据库记录。

选项

名称类型必填描述
dataXOR<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: '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 起在预览中。
relationLoadStrategy'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 条件,则创建新的数据库记录

选项

名称类型必填描述
createXOR<UserCreateInput,
UserUncheckedCreateInput>
将模型的所有字段包装在类型中,以便在创建新记录时可以提供这些字段。它还包括关系字段,允许执行(事务性)嵌套插入。在数据模型中标记为可选或具有默认值的字段是可选的。
updateXOR<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 查询交给数据库处理。了解更多

示例

更新(如果存在)或创建 emailalice@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

数据库 upserts 具有以下优势

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

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

数据库 upsert 前提条件

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

  • 您使用 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 起在预览中。
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 等于 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>将所有模型字段包装在一个类型中,以便在创建新记录时提供它们。数据模型中标记为可选或具有默认值的字段是可选的。
是否跳过重复项?布尔值不要插入具有已存在的唯一字段或 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>指定应在返回对象上急切加载哪些关系
是否跳过重复项?布尔值不要插入具有已存在的唯一字段或 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包装模型所有字段,以便可以按任何属性过滤列表。如果您不过滤列表,将更新所有记录。
limitnumber限制要更新的记录数量。

返回类型

返回类型示例描述
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包装模型所有字段,以便可以按任何字段过滤列表。
limitInt限制删除的记录数量。

返回类型

返回类型示例描述
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>
允许您按任何属性对返回的列表进行排序。
cursorUserWhereUniqueInput指定列表的位置(该值通常指定 id 或其他唯一值)。
takenumber指定列表中应返回多少个对象(从列表的开头(正值)或结尾(负值)从提及的 cursor 位置来看)
skipnumber指定列表中应跳过多少个返回对象。

返回类型

返回类型示例描述
number29记录计数。
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)
  • 所有具有非 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,并返回每组 profileViews_sum

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

const groupUsers = await prisma.user.groupBy({
by: ['country', 'city'],
_count: {
_all: true,
city: true,
},
_sum: {
profileViews: true,
},
orderBy: {
country: 'desc',
},
having: {
profileViews: {
_avg: {
gt: 200,
},
},
},
});
显示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
},
});
创建新的 User 记录并带有两条 Post 记录时,在返回的对象中包含 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 - 如果 id 匹配,此类型将更新 Post 记录的 title 字段;如果不存在,则会创建它。

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

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

orderBy

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

备注

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

信息

对于 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 的记录列表中去重。另请参见:聚合、分组和汇总

示例

在单个字段上选择去重

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

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

以下示例返回所有不同的 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' },
];

请注意,现在除了 "Paris, France" 之外,还有一个 "Paris, Denmark"

结合过滤器选择去重

以下示例返回用户电子邮件包含 "prisma.io" 的所有不同的 city country 字段组合,并且只选择 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

示例

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

由于是一对多关系,您还可以通过向 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>将所有模型字段包装在一个类型中,以便在创建新记录时提供它们。数据模型中标记为可选或具有默认值的字段是可选的。
是否跳过重复项?布尔值不要插入具有已存在的唯一字段或 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 记录列表。参见:使用关联

示例

更新现有 User 记录,断开所有之前的 Post 记录连接,并连接两个其他现有记录
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 之前应用 connectset 操作将通过清除所有已连接的记录并用其自己指定的状体替换它们来覆盖 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. 尝试将配置文件连接到电子邮件地址为 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. 如果不存在匹配的配置文件,则创建新的配置文件
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 查询如果相关记录存在则更新,否则创建新的相关记录。

示例

通过更新与其连接的 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' },
},
},
},
});
通过更新与其连接的两个 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 仅在关联是可选时可用。

示例

通过删除与其连接的 Profile 记录来更新现有 User 记录
const user = await prisma.user.update({
where: { email: 'alice@prisma.io' },
data: {
profile: {
delete: true,
},
},
});
通过删除与其连接的两个 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',
},
},
});
warning

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

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

in

n 存在于列表中。

note

不会返回 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 连接器支持

示例

获取所有 Post 记录,其中 title 不区分大小写地包含 prisma
const result = await prisma.post.findMany({
where: {
title: {
contains: 'prisma',
mode: 'insensitive',
},
},
});

startsWith

示例

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

endsWith

获取所有 User 记录,其中 emailprisma.io 结尾

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

AND

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

示例

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

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

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

以下示例结合了 ORAND

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

OR

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

示例

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

以下示例结合了 ORNOT

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

以下示例结合了 ORAND

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

NOT

所有条件必须返回 false

示例

获取所有 Post 记录,其中 title 不包含 SQL
const result = await prisma.post.findMany({
where: {
NOT: {
title: {
contains: 'SQL',
},
},
},
});
获取所有 Post 记录,其中 title 字段包含 Prismadatabases,但不包含 SQL,且关联的 User 记录的电子邮件地址不包含 sarah
const result = await prisma.post.findMany({
where: {
OR: [
{
title: {
contains: 'Prisma',
},
},
{
title: {
contains: 'databases',
},
},
],
NOT: {
title: {
contains: 'SQL',
},
},
user: {
NOT: {
email: {
contains: 'sarah',
},
},
},
},
include: {
user: true,
},
});

关联过滤

some

返回所有记录,其中一个或多个(“some”)关联记录匹配过滤条件。

备注

  • 可以在不带参数的情况下使用 some 来返回所有至少存在一个关联的记录

示例

获取所有 User 记录,其中部分文章提及了 Prisma
const result = await prisma.user.findMany({
where: {
post: {
some: {
content: {
contains: "Prisma"
}
}
}
}
}

every

返回所有记录,其中所有(“every”)关联记录都匹配过滤条件。

示例

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

none

返回所有记录,其中零个关联记录匹配过滤条件。

备注

示例

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

is

返回所有关联记录匹配过滤条件的记录(例如,用户的名字 is Bob)。

示例

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

isNot

返回所有关联记录不匹配过滤条件的记录(例如,用户的名字 isNot Bob)。

示例

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

标量列表方法

set

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

备注

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

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

示例

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

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

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

push

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

备注

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

示例

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

warning

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

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

示例

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

标量列表过滤器

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

warning

适用于

备注

  • 标量列表/数组过滤器忽略 NULL。使用 isEmptyNOT 不会返回包含 NULL 值列表/数组的记录,并且 { equals: null } 会导致错误。

has

指定的值存在于列表中。

示例

以下查询返回所有 Post 记录,其中 tags 列表包含 "databases"

const posts = await client.post.findMany({
where: {
tags: {
has: 'databases',
},
},
});

以下查询返回所有 Post 记录,其中 tags 列表不包含 "databases"

const posts = await client.post.findMany({
where: {
NOT: {
tags: {
has: 'databases',
},
},
},
});

hasEvery

列表中的每个值都存在。

示例

以下查询返回所有 Post 记录,其中 tags 列表至少包含 "databases" "typescript"

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

hasSome

列表中至少存在一个值。

示例

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

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

isEmpty

列表为空。

示例

以下查询返回所有没有标签的 Post 记录

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

isSet

warning

此过滤器仅在 MongoDB 3.11.1 及更高版本中可用。

过滤列表,仅包含已设置(设置为某个值,或显式设置为 null)的结果。将此过滤器设置为 true 将排除未设置的 undefined 结果。

示例

以下查询返回所有 Post 记录,其中 tags 已被设置为 null 或某个值

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

equals

列表完全匹配指定的值。

示例

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

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

复合类型方法

warning

仅在 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' }],
},
},
});

复合类型过滤器

warning

仅在 Prisma 3.11.0 及更高版本的 MongoDB 中可用。

复合类型过滤器允许您过滤复合类型的内容。

equals

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

备注

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

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

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

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

示例

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

is

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

示例

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

isNot

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

示例

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

isEmpty

使用 isEmpty 过滤复合类型空列表的结果。

示例

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

every

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

示例

查找第一件产品,其中每张照片的 height 都为 200
const product = 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字段

warning

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

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

客户端方法

注意:客户端级别的方法以$开头。

备注

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

扩展客户端中,客户端方法不一定存在。如果正在扩展客户端,请在使用$transaction$connect等客户端方法之前检查其是否存在。

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

$disconnect()

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

备注

  • $disconnect()返回一个Promise,所以应该在async函数内部使用await关键字调用它。

$connect()

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

备注

  • $connect()返回一个Promise,所以应该在async函数内部使用await关键字调用它。

$on()

warning

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

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

$use()

warning

$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帮助您基于schema模型创建可重用的查询参数,同时确保创建的对象有效。另请参阅:使用Prisma.validator

使用validator有两种方式

使用生成的Prisma Client类型

使用类型提供了一种类型级别的数据验证方法

Prisma.validator<GeneratedType>({ args });

使用“选择器”

使用选择器模式时,您使用现有的Prisma Client实例来创建validator。此模式允许您选择要验证的模型、操作和查询选项。

您还可以使用通过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
  • 嵌套 disconnect
  • 嵌套删除

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

嵌套更新示例
await prisma.user.update({
where: { id: 1, },
data: {
to_one: {
// Before Prisma version 4.5.0
update: { field: "updated" }
// From Prisma version 4.5.0, you can also do the following:
update: { where: { /*WhereInput*/ }, data: { field: "updated" } } }
}
}
})
嵌套 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 */ },
}
}
}
})
嵌套 disconnect 示例
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能够将所有查询作为一个事务传递给查询引擎。