跳至主要内容

Prisma Client API 参考

Prisma Client API 参考文档基于以下模式

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

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

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

enum Role {
USER
ADMIN
}

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

PrismaClient

本节介绍 PrismaClient 构造函数及其参数。

备注

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

datasources

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

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

属性

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

备注

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

示例

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

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

基于以下 datasource

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

datasourceUrl

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

属性

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

示例

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

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

log

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

选项

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

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

对于 MongoDB,这会使用 mongosh shell 格式记录查询。示例
prisma:query db.User.deleteMany({ _id: ( $in: [ “6221ce49f756b0721fc00542”, ], }, })
info示例
prisma:info 在 http://127.0.0.1:58471 上启动了 http 服务器
warn警告。
error错误。
发射格式
名称描述
stdout参见:stdout
event引发您可以订阅的事件。
事件类型

query 事件类型

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

错误格式

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

示例

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

adapter

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

info

此功能从 5.4.0 及更高版本开始可用,位于 driverAdapters 功能标志后面。

示例

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

import { Pool, neonConfig } from '@neondatabase/serverless';
import { PrismaNeon } from '@prisma/adapter-neon';
import { PrismaClient } from '@prisma/client';
import dotenv from 'dotenv';
import ws from 'ws';

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

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

rejectOnNotFound

info

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

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

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

备注

选项

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

示例

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

transactionOptions

info

注意transactionOptions是在 v5.10.0 中引入的。

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

备注

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

选项

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

示例

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

模型查询

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

findUnique()

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

  • 通过ID
  • 通过唯一属性

findUnique()在版本2.12.0中替换了findOne

备注

选项

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

返回类型

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

示例

获取id42User记录
const result = await prisma.user.findUnique({
where: {
id: 42,
},
});
获取email[email protected]User记录
const result = await prisma.user.findUnique({
where: {
email: '[email protected]',
},
});
获取firstNameAlicelastNameSmithUser记录(@@unique
展开示例 User 模型,其中包含 @@unique 块
model User {
firstName String
lastName String

@@unique(fields: [firstName, lastName], name: "fullname")
}
const result = await prisma.user.findUnique({
where: {
fullname: {
// name property of @@unique attribute - default is firstname_lastname
firstName: 'Alice',
lastName: 'Smith',
},
},
});
获取firstNameAlicelastNameSmithUser记录(@@id
展开示例 User 模型,其中包含 @@id 块
model User {
firstName String
lastName String

@@id([firstName, lastName])
}
const result = await prisma.user.findUnique({
where: {
firstName_lastName: {
firstName: 'Alice',
lastName: 'Smith',
},
},
});

findUniqueOrThrow()

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

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

这是一个用法示例

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

findUniqueOrThrow()findUnique()的不同之处在于

  • 它的返回类型是非空的。例如,post.findUnique()可以返回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>
允许您按任何属性对返回的列表进行排序。
cursor

UserWhereUniqueInput指定列表的位置(该值通常指定一个id或其他唯一值)。
获取数量指定列表中应返回多少个对象(从开头(正值)或结尾(负值)或者如果已提及,则从cursor位置开始查看)。
跳过数量指定应跳过列表中返回对象的多少个。
唯一Enumerable<UserDistinctFieldEnum>允许您按特定字段过滤掉重复行 - 例如,仅返回唯一的Post标题。

返回类型

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

示例

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

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

create()

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

选项

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

返回类型

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

备注

  • 您还可以执行嵌套的create - 例如,同时添加一个User和两个Post记录。

示例

创建一个仅包含必填字段email的新记录
const user = await prisma.user.create({
data: { email: '[email protected]' },
});
创建多个新记录

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

以下示例将导致两个INSERT语句

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

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

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

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

main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
显示CLI结果
prisma:query BEGIN
prisma:query INSERT INTO "public"."User" ("name","email","profileViews","role","coinflips") VALUES ($1,$2,$3,$4,$5) RETURNING "public"."User"."id"
prisma:query SELECT "public"."User"."id", "public"."User"."name", "public"."User"."email", "public"."User"."profileViews", "public"."User"."role", "public"."User"."coinflips" FROM "public"."User" WHERE "public"."User"."id" = $1 LIMIT $2 OFFSET $3
prisma:query INSERT INTO "public"."User" ("name","email","profileViews","role","coinflips") VALUES ($1,$2,$3,$4,$5) RETURNING "public"."User"."id"
prisma:query COMMIT
prisma:query SELECT "public"."User"."id", "public"."User"."name", "public"."User"."email", "public"."User"."profileViews", "public"."User"."role", "public"."User"."coinflips" FROM "public"."User" WHERE "public"."User"."id" = $1 LIMIT $2 OFFSET $3
prisma:query COMMIT

update()

update 更新现有的数据库记录。

选项

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

返回类型

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

备注

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

示例

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

upsert()

info

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

upsert执行以下操作

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

选项

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

返回类型

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

备注

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

示例

更新(如果存在)或创建一个新的email[email protected]User记录
const user = await prisma.user.upsert({
where: { id: 1 },
update: { email: '[email protected]' },
create: { email: '[email protected]' },
});

upsert 操作中的唯一键约束错误

问题

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

原因

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

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

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

解决方案

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

数据库 upsert

在可能的情况下,Prisma Client 将upsert查询交给数据库处理。这称为数据库 upsert

数据库 upsert 具有以下优点

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

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

数据库 upsert 先决条件

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

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

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

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

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

数据库 upsert 示例

以下示例使用此模式

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

@@unique([id, profileViews])
}

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

prisma.user.upsert({
where: {
userName: 'Alice',
},
create: {
id: 1,
profileViews: 1,
userName: 'Alice',
email: '[email protected]',
},
update: {
email: '[email protected]',
},
});

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

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

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

prisma.User.upsert({
where: {
userName: 'Alice',
profileViews: 1,
id: 1,
},
create: {
id: 1,
profileViews: 1,
userName: 'Alice',
email: '[email protected]',
},
update: {
email: '[email protected]',
},
});

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

prisma.User.upsert({
where: {
userName: 'Alice',
},
create: {
id: 1,
profileViews: 1,
userName: 'AliceS',
email: '[email protected]',
},
update: {
email: '[email protected]',
},
});

在以下查询中,poststitle 字段上的选择是一个嵌套读取,因此 Prisma Client 使用数据库 upsert。

prisma.user.upsert({
select: {
email: true,
id: true,
posts: {
select: {
title: true,
},
},
},
where: {
userName: 'Alice',
},

create: {
id: 1,
profileViews: 1,
userName: 'Alice',
email: '[email protected]',
},
update: {
email: '[email protected]',
},
});

delete()

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

  • 通过ID
  • 通过唯一属性

要删除与特定条件匹配的记录,请使用带过滤器的 deleteMany

选项

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

返回类型

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

备注

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

示例

删除 id1User 记录
const user = await prisma.user.delete({
where: { id: 1 },
});
删除 email 等于 [email protected]User 记录

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

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

createMany()

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

选项

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

返回类型

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

备注

  • 从 Prisma ORM 5.12.0 版本开始,SQLite 现在支持 createMany()
  • MongoDB、SQLServer 或 SQLite 不支持 skipDuplicates 选项。
  • 不能使用嵌套的 createcreateManyconnectconnectOrCreate 查询在顶级 createMany() 查询中创建或连接关系。
  • 您可以在 update()create() 查询中使用嵌套的 createMany 查询 - 例如,同时添加一个 User 和两个 Post 记录,并使用嵌套的 createMany

示例

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

createManyAndReturn()

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

info

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

选项

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

备注

  • SQLite 不支持 skipDuplicates 选项。
  • 不能使用嵌套的 createcreateManyconnectconnectOrCreate 查询在顶级 createManyAndReturn() 查询中创建或连接关系。
  • 当通过 include 包含关系时,每个关系都会生成一个单独的查询。
  • 不支持 relationLoadStrategy: join

返回类型

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

示例

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

updateMany()

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

选项

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

返回类型

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

示例

将所有 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',
},
});

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

有关如何过滤要删除的记录的示例,请参阅 过滤器条件和运算符

count()

选项

名称类型必需描述
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性过滤列表。
orderByXOR<Enumerable<PostOrder
ByInput>, PostOrderByInput>
允许您按任何属性对返回的列表进行排序。
cursor

UserWhereUniqueInput指定列表的位置(该值通常指定一个id或其他唯一值)。
获取数量指定列表中应返回多少个对象(从开头(正值)或结尾(负值)或者如果已提及,则从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)
  • 所有具有非 `null` `name` 字段的记录的计数
  • 所有具有非 `null` `city` 字段的记录的计数
const c = await prisma.user.count({
select: {
_all: true,
city: true,
name: true,
},
});

aggregate()

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

选项

名称类型必需描述
whereUserWhereInput所有模型字段包装在类型中,以便可以通过任何属性过滤列表。
orderByXOR<Enumerable<UserOrderByInput>,
UserOrderByInput>
允许您按任何属性对返回的列表进行排序。
cursor

UserWhereUniqueInput指定列表的位置(该值通常指定一个id或其他唯一值)。
获取数量指定列表中应返回多少个对象(从开头(正值)或结尾(负值)或者如果已提及,则从cursor位置开始查看)。
跳过数量指定应跳过列表中返回对象的多少个。
_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 的组。
获取数量指定列表中应返回多少个对象(从开头(正值)或结尾(负值)或者如果已提及,则从cursor位置开始查看)。
跳过数量指定应跳过列表中返回对象的多少个。
_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` 记录的 `name` 和 `profileViews` 字段
const result = await prisma.user.findUnique({
where: { id: 1 },
select: {
name: true,
profileViews: true,
},
});
显示CLI结果
选择多个 `User` 记录的 `email` 和 `role` 字段
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结果
include 在 `select` 中
const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
include: {
author: true,
},
},
},
});
显示CLI结果

select 的生成类型

以下示例演示了如何将 validator 与 `select` 一起使用

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

include

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

备注

示例

在加载 `User` 记录时包含 `posts` 和 `profile` 关系
const users = await prisma.user.findMany({
include: {
posts: true, // Returns all fields for all posts
profile: true, // Returns all Profile fields
},
});
在使用两个 `Post` 记录创建新的 `User` 记录时,在返回的对象上包含 `posts` 关系
const user = await prisma.user.create({
data: {
email: '[email protected]',
posts: {
create: [{ title: 'This is my first post' }, { title: 'Here comes a second post' }],
},
},
include: { posts: true }, // Returns all fields for all posts
});

include 的生成类型

以下示例演示了如何将 validator 与 `include` 一起使用

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

omit (预览)

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

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

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

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

备注

  • 您不能组合 `omit` 和 `select`,因为它们具有相反的目的

示例

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

omit 的生成类型

以下示例演示了如何将 validator 与 `omit` 一起使用

const omitPassword = Prisma.validator<Prisma.UserOmit>()({
password: true,
});

relationLoadStrategy (预览)

relationLoadStrategy 指定关系应如何从数据库中加载。它有两个可能的值

  • join (默认):使用数据库级别的 `LATERAL JOIN` (PostgreSQL) 或相关子查询 (MySQL),并使用单个查询到数据库中获取所有数据。
  • query:向数据库发送多个查询(每个表一个),并在应用程序级别将它们连接起来。

注意:一旦relationLoadStrategy预览版进入正式版join将普遍成为所有关系查询的默认策略。

您可以此处了解更多关于连接策略的信息。

因为relationLoadStrategy选项目前处于预览阶段,您需要通过Prisma模式文件中的relationJoins预览功能标志启用它。

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

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

备注

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

示例

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

where

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

示例

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

where的生成类型

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

  • UserWhereInput

    // UserWhereInput
    const whereNameIs = Prisma.validator<Prisma.UserWhereInput>()({
    name: 'Rich',
    });

    // It can be combined with conditional operators too
    const whereNameIs = Prisma.validator<Prisma.UserWhereInput>()({
    name: 'Rich',
    AND: [
    {
    email: {
    contains: '[email protected]',
    },
    },
    ],
    });
  • UserWhereUniqueInput此类型通过公开模型上的任何唯一字段来工作。分配了@id的字段被视为唯一字段,分配了@unique的字段也是如此。

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

    // UserWhereUniqueInput
    const whereEmailIsUnique = Prisma.validator<Prisma.UserWhereUniqueInput>()({
    email: '[email protected]',
    })
  • PostScalarWhereInput

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

    const updatePostByIdWithoutAuthor =
    Prisma.validator<Prisma.PostUpdateWithWhereUniqueWithoutAuthorInput>()({
    where: {
    id: 1,
    },
    data: {
    content: 'This is some updated content',
    published: true,
    title: 'This is a new title',
    },
    });
  • PostUpsertWithWhereUniqueWithoutAuthorInput - 此类型将更新其中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排序

info

对于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排序 - emailrole

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

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

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

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

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

const users3 = await prisma.user.findMany({
orderBy: {
email: 'asc',
},
select: {
name: true,
email: true,
},
});
显示CLI结果
emailUser记录排序,并按title对嵌套的Post记录排序

以下示例

  • 返回按email排序的所有User记录。
  • 对于每个User记录,返回按title排序的所有嵌套Post记录的title字段。
const usersWithPosts = await prisma.user.findMany({
orderBy: {
email: 'asc',
},
include: {
posts: {
select: {
title: true,
},
orderBy: {
title: 'asc',
},
},
},
});
显示CLI结果
对一个用户的嵌套Post记录列表进行排序

以下示例通过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' },
];
对多个字段进行去重选择

以下示例返回所有不同的 citycountry 字段组合,并且仅选择 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' },
];

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

结合过滤器进行去重选择

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

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

嵌套查询

create

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

备注

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

示例

创建具有新 Profile 记录的新 User 记录
const user = await prisma.user.create({
data: {
email: '[email protected]',
profile: {
create: { bio: 'Hello World' },
},
},
});
创建具有新 User 记录的新 Profile 记录
const user = await prisma.profile.create({
data: {
bio: 'Hello World',
user: {
create: { email: '[email protected]' },
},
},
})
创建具有新 Post 记录的新 User 记录
const user = await prisma.user.create({
data: {
email: '[email protected]',
posts: {
create: { title: 'Hello World' },
},
},
});
创建具有两个新 Post 记录的新 User 记录

由于它是一对多关系,您还可以通过将数组传递给 create 来一次创建多个 Post 记录。

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

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

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

createMany

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

备注

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

选项

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

示例

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

set

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

示例

通过断开任何以前的 Post 记录并连接另外两个现有记录来更新现有的 User 记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
posts: {
set: [{ id: 32 }, { id: 42 }],
},
},
});

connect

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

备注

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

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

    The required connected records were not found. Expected 1 records to be connected, found 0.

示例

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

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

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

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

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

connectOrCreate

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

备注

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

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

以下示例

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

disconnect

嵌套的disconnect查询会断开父记录和相关记录之间的连接,但不会删除任何记录。参见:关系操作

备注

  • 仅当关系是可选时,disconnect才可用。

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

    • (在 2.21.0 及更高版本中), 操作将不执行任何操作

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

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

示例

更新现有的User记录,断开它连接到的Profile记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
disconnect: true,
},
},
});
更新现有的User记录,断开它连接到的两个Post记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
posts: {
disconnect: [{ id: 44 }, { id: 46 }],
},
},
});

update

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

备注

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

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

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

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

示例

更新现有的User记录,更新它连接到的Profile记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
profile: {
update: { bio: 'Hello World' },
},
},
});
更新现有的User记录,更新它连接到的两个Post记录
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: {
posts: {
update: [
{
data: { published: true },
where: { id: 32 },
},
{
data: { published: true },
where: { id: 23 },
},
],
},
},
});

upsert

info

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

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

示例

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

delete

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

备注

  • 仅当关系是可选时,delete才可用。

示例

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

updateMany

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

示例

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

deleteMany

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

示例

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

过滤条件和运算符

info

equals

值等于n

示例

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

您还可以排除equals

const result = await prisma.user.findMany({
where: {
name: 'Eleanor',
},
});
返回所有数量低于“警告数量”阈值的商品

此示例比较同一模型的字段,该功能自 4.3.0 版本起可用。

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

not

值不等于n

示例

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

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

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

in

n存在于列表中。

注意

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

示例

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

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

const getUser = await prisma.user.findMany({
where: {
NOT: {
name: { in: ['Saqui', 'Clementine', 'Bob'] },
},
},
});
获取至少一个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值。

示例

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

lt

n小于x

示例

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

lte

n小于**或**等于x

示例

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

gt

n大于x

示例

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

gte

n大于**或**等于x

示例

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

示例

获取所有date_created大于2020年3月19日的Post记录
const result = await prisma.post.findMany({
where: {
date_created: {
gte: new Date('2020-03-19T14:21:00+0200') /* Includes time offset for UTC */,
},
},
});

contains

n包含x

示例

统计所有content包含databasesPost记录
const result = await prisma.post.count({
where: {
content: {
contains: 'databases',
},
},
});
统计所有content**不**包含databasesPost记录
const result = await prisma.post.count({
where: {
NOT: {
content: {
contains: 'databases',
},
},
},
});

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

info

对于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包含prismaPost记录,不区分大小写
const result = await prisma.post.findMany({
where: {
title: {
contains: 'prisma',
mode: 'insensitive',
},
},
});

startsWith

示例

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

endsWith

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

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

AND

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

示例

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

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

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

以下示例结合了ORAND

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

OR

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

示例

获取所有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。
  • 您可以推送值的列表或仅推送单个值。

示例

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

unset

警告

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

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

示例

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

标量列表过滤器

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

警告

适用于

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

备注

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

警告

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

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

示例

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

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

equals

列表完全匹配给定值。

示例

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

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

复合类型方法

警告

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

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

set

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

备注

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

示例

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

unset

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

示例

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

update

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

备注

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

示例

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

upsert

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

备注

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

示例

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

push

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

示例

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

复合类型过滤器

警告

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

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

equals

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

备注

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

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

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

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

示例

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

is

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

示例

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

isNot

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

示例

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

isEmpty

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

示例

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

every

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

示例

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

some

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

示例

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

none

使用 none 过滤复合类型列表,其中列表中的任何项目都不匹配条件。

示例

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

原子数字运算

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

概述:竞争条件

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

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

22
客户端 1设置字段值

22

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

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

运算符

选项描述
增量n添加到当前值。
减量从当前值中减去n
乘法将当前值乘以n
除法将当前值除以n
设置设置当前字段值。与{ 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数组包含名称值为"Dreamies"的对象的用户

const getUsers = await prisma.user.findMany({
where: {
pets: {
path: '$.favorites.treats[*].name',
array_contains: 'Dreamies',
},
},
});

string_contains

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

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

string_starts_with

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

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

string_ends_with

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

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

array_contains

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

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

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

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

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

array_starts_with

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

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

array_ends_with

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

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

客户端方法

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

备注

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

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

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

$disconnect()

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

备注

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

$connect()

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

备注

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

$on()

警告

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

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

$use()

警告

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

$use()方法添加中间件

prisma.$use(async (params, next) => {
console.log('This is middleware!');
// Modify or interrogate params here

return next(params);
});

next

next表示中间件堆栈中的“下一级”,这可能是下一个中间件或 Prisma 查询,具体取决于您在堆栈中的位置

params

params是一个包含要在中间件中使用信息的 对象。

参数描述
action查询类型 - 例如,createfindMany
args传递给查询的参数 - 例如,wheredataorderBy
dataPath如果您使用流畅 API,则会填充。
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 预览功能使用。

info

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

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

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

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

fields 是每个模型的特殊属性。它包含该模型的字段列表。

注意事项

字段必须具有相同的类型

您只能对相同类型的字段进行比较。例如,以下操作会导致错误

await prisma.order.findMany({
where: {
id: { equals: prisma.order.fields.due },
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Type error: id is a string, while amountDue is an integer
},
});

字段必须位于同一模型中

您只能使用 fields 属性对同一模型中的字段进行比较。以下示例无效

await prisma.order.findMany({
where: {
id: { equals: prisma.user.fields.name },
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Type error: name is a field on the User model, not Order
},
});

但是,您可以使用 标准查询 比较不同模型中的字段。

groupBy 模型查询中,将引用的字段放在 by 参数中

如果您将 groupBy 模型查询与 having 选项一起使用,则必须将引用的字段放在 by 参数中。

以下示例有效

prisma.user.groupBy({
by: ['id', 'name'],
having: { id: { equals: prisma.user.fields.name } },
});

以下示例无效,因为 name 不在 by 参数中

prisma.user.groupBy({
by: ['id'],
having: { id: { equals: prisma.user.fields.name } },
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// name is not in the 'by' argument
});

在标量列表中搜索字段

如果您的数据源支持标量列表(例如在 PostgreSQL 中),则可以搜索所有特定字段位于字段列表中的记录。为此,请使用 innotIn 筛选器引用标量列表。例如

await prisma.user.findMany({
where: {
// find all users where 'name' is in a list of tags
name: { in: prisma.user.fields.tags },
},
});

使用 UserWhereUniqueInput 筛选非唯一字段

从 5.0.0 版本开始,where 上生成的类型 UserWhereUniqueInput 公开了模型上的所有字段,而不仅仅是唯一字段。这在 4.5.0 到 4.16.2 版本之间的 extendedWhereUnique 预览标志 下可用

您必须在 where 语句中 布尔运算符之外 指定至少一个唯一字段,并且可以指定任意数量的其他唯一和非唯一字段。您可以使用它向返回单个记录的任何操作添加筛选器。例如,您可以将此功能用于以下操作

从 4.6.0 版本开始,您可以使用此功能筛选可选的 一对一嵌套读取

更新操作上的乐观并发控制

您可以筛选非唯一字段以对 update 操作执行 乐观并发控制

要执行乐观并发控制,我们建议您使用 version 字段来检查记录或相关记录中的数据在代码执行期间是否已更改。在 4.5.0 版本之前,您无法在 update 操作中评估 version 字段,因为该字段是非唯一的。从 4.5.0 版本开始,您可以评估 version 字段。

在以下示例中,updateOneupdateTwo 首先读取同一记录,然后尝试更新它。数据库仅在 version 中的值与初始读取时相同的情况下执行这些更新。当数据库执行第一个更新(可能是 updateOneupdateTwo,具体取决于时间)时,它会递增 version 中的值。这意味着数据库不会执行第二个更新,因为 version 中的值已更改。

model User {
id Int @id @default(autoincrement())
email String @unique
city String
version Int
}
function updateOne() {
const user = await prisma.user.findUnique({ id: 1 });

await prisma.user.update({
where: { id: user.id, version: user.version },
data: { city: 'Berlin', version: { increment: 1 } },
});
}

function updateTwo() {
const user = await prisma.user.findUnique({ id: 1 });

await prisma.user.update({
where: { id: user.id, version: user.version },
data: { city: 'New York', version: { increment: 1 } },
});
}

function main() {
await Promise.allSettled([updateOne(), updateTwo()]);
}

权限检查

您可以筛选非唯一字段以在更新期间检查权限。

在以下示例中,用户希望更新帖子标题。where 语句检查 authorId 中的值以确认用户是否是帖子的作者。仅当用户是帖子作者时,应用程序才会更新帖子标题。

await prisma.post.update({
where: { id: 1, authorId: 1 },
data: { title: 'Updated post title' },
});

软删除

您可以筛选非唯一字段来处理软删除。

在以下示例中,我们不希望在帖子被软删除的情况下返回它。该操作仅在isDeleted的值为false时返回帖子。

prisma.Post.findUnique({ where: { id: postId, isDeleted: false } });

UserWhereUniqueInput 注意事项

使用布尔运算符与UserWhereUniqueInput

使用UserWhereUniqueInput时,必须在布尔运算符ANDORNOT之外指定至少一个唯一字段。您仍然可以在过滤器中将这些布尔运算符与任何其他唯一字段或非唯一字段结合使用。

在以下示例中,我们测试了id(一个唯一字段)以及email。这是有效的。

await prisma.user.update({
where: { id: 1, OR: [{ email: "[email protected]" }, { email: "[email protected]" }] },
// ^^^ Valid: the expression specifies a unique field (`id`) outside of any boolean operators
data: { ... }
})

// SQL equivalent:
// WHERE id = 1 AND (email = "[email protected]" OR email = "[email protected]")

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

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

一对一关系

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

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

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

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

PrismaPromise 行为

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

例如

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

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

当使用 $transaction API 时,此行为使 Prisma Client 可以将所有查询作为单个事务传递到查询引擎。