Prisma 客户端 API 参考(Prisma Client API Reference)

Verified 中级 Intermediate 参考型 Reference ⚡ Claude Code 专属 ⚡ Claude Code Optimized
14 min read · 708 lines

Prisma 官方 Client API:CRUD + 过滤器 + 关系查询 + 事务 + 聚合

Prisma 客户端 API 参考(Prisma Client API Reference)

概述

Prisma Client 是 Prisma ORM 的核心查询接口,提供类型安全的数据库操作。本文档涵盖模型查询、过滤器、关联操作、事务和客户端方法,适用于 Prisma ORM 7.x 版本。

适用场景

  • 使用 Prisma Client 编写数据库查询
  • 执行 CRUD 操作(创建、读取、更新、删除)
  • 数据过滤和排序
  • 操作关联数据
  • 使用事务(Transaction)
  • 配置客户端选项

规则优先级

优先级 分类 影响程度 前缀
1 客户端构造 constructor
2 模型查询 关键 model-queries
3 查询选项 query-options
4 过滤器 filters
5 关联 relations
6 事务 关键 transactions
7 原始 SQL 关键 raw-queries
8 客户端方法 client-methods

客户端实例化(v7)

import { PrismaClient } from '../generated/client'
import { PrismaPg } from '@prisma/adapter-pg'

const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL
})

const prisma = new PrismaClient({ adapter })

模型查询方法

方法 说明 返回类型
findUnique() 通过唯一字段查找单条记录 Record | null
findUniqueOrThrow() 查找单条,未找到则抛错 Record
findFirst() 查找第一条匹配记录 Record | null
findFirstOrThrow() 查找第一条,未找到则抛错 Record
findMany() 查找多条记录 Record[]
create() 创建一条新记录 Record
createMany() 批量创建记录 { count: number }
createManyAndReturn() 批量创建并返回记录 Record[]
update() 更新一条记录 Record
updateMany() 批量更新记录 { count: number }
updateManyAndReturn() 批量更新并返回记录 Record[]
upsert() 更新或创建记录 Record
delete() 删除一条记录 Record
deleteMany() 批量删除记录 { count: number }
count() 统计匹配记录数 number
aggregate() 聚合运算(求和、平均值等) Aggregate result
groupBy() 分组聚合 Group result[]

查询选项

选项 说明
where 过滤条件
select 选择要返回的字段
include 加载关联数据
omit 排除指定字段
orderBy 排序方式
take 限制返回数量
skip 跳过记录数(分页)
cursor 游标分页(Cursor-based Pagination)
distinct 仅返回唯一值

读取操作

通过唯一字段查找

// 通过唯一字段查找
const user = await prisma.user.findUnique({
  where: { email: 'alice@prisma.io' }
})

// 复合唯一键(Composite Unique Key)
// 模型定义:@@unique([firstName, lastName])
const user = await prisma.user.findUnique({
  where: {
    firstName_lastName: {
      firstName: 'Alice',
      lastName: 'Smith'
    }
  }
})

查找第一条匹配

const user = await prisma.user.findFirst({
  where: { role: 'ADMIN' },
  orderBy: { createdAt: 'desc' }
})

查找多条记录

const users = await prisma.user.findMany({
  where: { role: 'USER' },
  orderBy: { name: 'asc' },
  take: 10,
  skip: 0
})

查找或抛错

// 未找到时抛出 PrismaClientKnownRequestError
const user = await prisma.user.findUniqueOrThrow({
  where: { id: 1 }
})

创建操作

创建单条记录

const user = await prisma.user.create({
  data: {
    email: 'alice@prisma.io',
    name: 'Alice'
  }
})

创建时同时创建关联数据

const user = await prisma.user.create({
  data: {
    email: 'alice@prisma.io',
    posts: {
      create: [
        { title: 'First Post' },
        { title: 'Second Post' }
      ]
    }
  },
  include: { posts: true }
})

批量创建

const result = await prisma.user.createMany({
  data: [
    { email: 'alice@prisma.io', name: 'Alice' },
    { email: 'bob@prisma.io', name: 'Bob' }
  ],
  skipDuplicates: true  // 跳过重复唯一字段的记录
})
// 返回 { count: 2 }

批量创建并返回

const users = await prisma.user.createManyAndReturn({
  data: [
    { email: 'alice@prisma.io', name: 'Alice' },
    { email: 'bob@prisma.io', name: 'Bob' }
  ]
})
// 返回创建的用户数组

更新操作

更新单条记录

const user = await prisma.user.update({
  where: { id: 1 },
  data: { name: 'Alice Smith' }
})

原子操作(Atomic Operations)

const post = await prisma.post.update({
  where: { id: 1 },
  data: {
    views: { increment: 1 },   // 递增
    likes: { decrement: 1 },   // 递减
    score: { multiply: 2 },    // 乘法
    rating: { divide: 2 },     // 除法
    version: { set: 5 }        // 直接设置
  }
})

批量更新

const result = await prisma.user.updateMany({
  where: { role: 'USER' },
  data: { verified: true }
})
// 返回 { count: 42 }

更新或创建(Upsert)

const user = await prisma.user.upsert({
  where: { email: 'alice@prisma.io' },
  update: { name: 'Alice Smith' },
  create: { email: 'alice@prisma.io', name: 'Alice' }
})

删除操作

// 删除单条记录
const user = await prisma.user.delete({
  where: { id: 1 }
})

// 批量删除
const result = await prisma.user.deleteMany({
  where: { role: 'GUEST' }
})
// 返回 { count: 5 }

// 删除全部
const result = await prisma.user.deleteMany({})

聚合操作

计数

const count = await prisma.user.count({
  where: { role: 'ADMIN' }
})

聚合(Aggregate)

const result = await prisma.post.aggregate({
  _avg: { views: true },
  _sum: { views: true },
  _min: { views: true },
  _max: { views: true },
  _count: { _all: true }
})

分组(GroupBy)

const groups = await prisma.user.groupBy({
  by: ['country'],
  _count: { _all: true },
  _avg: { age: true },
  having: {
    age: { _avg: { gt: 30 } }
  }
})

过滤器操作符

相等与不等

// 精确匹配(隐式)
where: { email: 'alice@prisma.io' }

// 显式 equals
where: { email: { equals: 'alice@prisma.io' } }

// 不等于
where: { email: { not: 'alice@prisma.io' } }

比较操作符

where: { age: { gt: 18 } }     // 大于
where: { age: { gte: 18 } }    // 大于等于
where: { age: { lt: 65 } }     // 小于
where: { age: { lte: 65 } }    // 小于等于
where: { age: { gte: 18, lte: 65 } }  // 组合使用

列表操作符

// 在数组中
where: { role: { in: ['ADMIN', 'MODERATOR'] } }

// 不在数组中
where: { role: { notIn: ['GUEST', 'BANNED'] } }

字符串过滤

where: { email: { contains: 'prisma' } }           // 包含
where: { email: { startsWith: 'alice' } }           // 以...开头
where: { email: { endsWith: '@prisma.io' } }        // 以...结尾

// 不区分大小写
where: {
  email: {
    contains: 'PRISMA',
    mode: 'insensitive'
  }
}

空值检查

where: { deletedAt: null }              // 为 null
where: { deletedAt: { not: null } }     // 不为 null
where: { middleName: { isSet: true } }  // 字段已设置(可选字段)

逻辑操作符

// AND(隐式 — 多个条件默认为 AND)
where: {
  email: { contains: '@prisma.io' },
  role: 'ADMIN'
}

// AND(显式)
where: {
  AND: [
    { email: { contains: '@prisma.io' } },
    { role: 'ADMIN' }
  ]
}

// OR
where: {
  OR: [
    { email: { contains: '@gmail.com' } },
    { email: { contains: '@prisma.io' } }
  ]
}

// NOT
where: {
  NOT: { role: 'GUEST' }
}

// 组合使用
where: {
  AND: [
    { verified: true },
    {
      OR: [
        { role: 'ADMIN' },
        { role: 'MODERATOR' }
      ]
    }
  ],
  NOT: { deletedAt: { not: null } }
}

关联过滤(Relation Filters)

操作符 说明
some 至少一条关联记录匹配
every 所有关联记录都匹配
none 没有关联记录匹配
is 关联记录匹配(一对一)
isNot 关联记录不匹配
// 有至少一篇已发布文章的用户
where: {
  posts: { some: { published: true } }
}

// 所有文章都已发布的用户
where: {
  posts: { every: { published: true } }
}

// 没有已发布文章的用户
where: {
  posts: { none: { published: true } }
}

// 一对一关联过滤
where: {
  profile: { is: { country: 'USA' } }
}

数组字段过滤

where: { tags: { has: 'typescript' } }                         // 包含元素
where: { tags: { hasSome: ['typescript', 'javascript'] } }     // 包含任一
where: { tags: { hasEvery: ['typescript', 'prisma'] } }        // 包含全部
where: { tags: { isEmpty: true } }                             // 为空

JSON 过滤

where: {
  metadata: {
    path: ['settings', 'theme'],
    equals: 'dark'
  }
}

关联查询

加载关联数据(Include)

const user = await prisma.user.findUnique({
  where: { id: 1 },
  include: {
    posts: true,
    profile: true
  }
})

过滤关联数据

const user = await prisma.user.findUnique({
  where: { id: 1 },
  include: {
    posts: {
      where: { published: true },
      orderBy: { createdAt: 'desc' },
      take: 5,
      select: { id: true, title: true }
    }
  }
})

嵌套关联

const user = await prisma.user.findUnique({
  where: { id: 1 },
  include: {
    posts: {
      include: {
        comments: {
          include: { author: true }
        }
      }
    }
  }
})

嵌套写入(Nested Writes)

// 创建时同时创建关联
const user = await prisma.user.create({
  data: {
    email: 'alice@prisma.io',
    posts: {
      create: [
        { title: 'Post 1' },
        { title: 'Post 2' }
      ]
    },
    profile: {
      create: { bio: 'Hello!' }
    }
  }
})

// 连接或创建(connectOrCreate)
const post = await prisma.post.create({
  data: {
    title: 'New Post',
    author: {
      connectOrCreate: {
        where: { email: 'alice@prisma.io' },
        create: { email: 'alice@prisma.io', name: 'Alice' }
      }
    }
  }
})

// 连接已有记录
const post = await prisma.post.create({
  data: {
    title: 'New Post',
    author: { connect: { id: 1 } }
  }
})

更新关联

// 更新关联记录
const user = await prisma.user.update({
  where: { id: 1 },
  data: {
    posts: {
      update: {
        where: { id: 1 },
        data: { title: 'Updated Title' }
      }
    }
  }
})

// 断开关联(Disconnect)
const user = await prisma.user.update({
  where: { id: 1 },
  data: {
    profile: { disconnect: true }
  }
})

// 替换所有关联(Set)
const post = await prisma.post.update({
  where: { id: 1 },
  data: {
    tags: { set: [{ id: 1 }, { id: 2 }] }
  }
})

统计关联数量

const users = await prisma.user.findMany({
  select: {
    name: true,
    _count: {
      select: { posts: true, followers: true }
    }
  }
})
// { name: 'Alice', _count: { posts: 5, followers: 100 } }

事务(Transactions)

顺序事务(Sequential)

const [user, post] = await prisma.$transaction([
  prisma.user.create({ data: { email: 'alice@prisma.io' } }),
  prisma.post.create({ data: { title: 'Hello', authorId: 1 } })
])

任何操作失败,所有操作都会回滚:

try {
  await prisma.$transaction([
    prisma.user.create({ data: { email: 'alice@prisma.io' } }),
    prisma.user.create({ data: { email: 'alice@prisma.io' } }) // 重复!
  ])
} catch (e) {
  // 两个操作都已回滚
}

交互式事务(Interactive)

适用于复杂逻辑和依赖操作:

await prisma.$transaction(async (tx) => {
  // 扣减发送方余额
  const sender = await tx.account.update({
    where: { id: senderId },
    data: { balance: { decrement: amount } }
  })

  // 检查余额
  if (sender.balance < 0) {
    throw new Error('Insufficient funds')  // 余额不足
  }

  // 增加接收方余额
  await tx.account.update({
    where: { id: recipientId },
    data: { balance: { increment: amount } }
  })
})

事务选项

await prisma.$transaction(
  async (tx) => {
    // 操作
  },
  {
    maxWait: 5000,    // 最大等待获取锁时间(毫秒)
    timeout: 10000,   // 最大事务持续时间(毫秒)
    isolationLevel: 'Serializable'  // 隔离级别
  }
)

隔离级别

级别 说明
ReadUncommitted 最低隔离,可读取未提交的更改
ReadCommitted 仅读取已提交的更改
RepeatableRead 事务内一致读取
Serializable 最高隔离,序列化执行

顺序事务 vs 交互式事务

特性 顺序事务 交互式事务
语法 数组 异步函数
依赖操作
条件逻辑
性能 更好 更灵活
用例 简单批处理 复杂逻辑

客户端方法

方法 说明
$connect() 显式连接到数据库
$disconnect() 断开数据库连接
$transaction() 执行事务
$queryRaw() 执行原始 SQL 查询
$executeRaw() 执行原始 SQL 命令
$on() 订阅事件
$extends() 添加扩展

最佳实践

保持事务简短

// 好的做法 — 仅在事务中执行数据库操作
const data = prepareData() // 在事务外准备数据
await prisma.$transaction(async (tx) => {
  await tx.user.create({ data })
})

错误处理

try {
  await prisma.$transaction(async (tx) => {
    // 操作
  })
} catch (e) {
  if (e.code === 'P2002') {
    // 处理唯一约束冲突
  }
  throw e
}

参考资源

相关技能 Related Skills