该文档的基础是建立在学过关系型数据库的基础上,并且以下内容是根据 API 文档进行参考编写的(没办法,概念那太零散了)。
https://prisma.yoga/getting-started
generator client {
provider = "prisma-client-js"
previewFeatures = ["orderByRelation"]
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model ExtendedProfile {
id Int @id @default(autoincrement())
biography String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model User {
id Int @id @default(autoincrement())
name String?
email String @unique
profileViews Int @default(0)
role Role @default(USER)
coinflips Boolean?
posts Post[]
profile ExtendedProfile?
}
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)
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
name String @unique
posts Post[]
}
enum Role {
USER
ADMIN
}
npx prisma db push
npx prisma generate
基本使用
查询选项
- 选项
orderBy
:排序- asc:升序
- desc:降序
distinct
:去重include
:定义了 Prisma 客户端返回的结果中包含哪些关系。
// orderBy
const users = await prisma.user.findMany({
orderBy: {
email: "asc",
},
/*
orderBy: [
{
role: 'desc',
},
{
name: 'desc',
},
],*/
});
// distinct
const distinctCities = await prisma.user.findMany({
select: {
city: true,
country: true,
},
distinct: ["city"],
});
// 返回所有 User 记录按 email 排序
// 对于每个 User 记录,返回按 title 排序的所有嵌套 Post 记录的 title 字段
const usersWithPosts = await prisma.user.findMany({
orderBy: {
email: "asc",
},
include: {
posts: {
select: {
title: true,
},
orderBy: {
title: "asc",
},
},
},
});
/*
[
{
"id": 2,
"email": "alice@prisma.io",
"name": "Alice",
"posts": [
{
"title": "Watch the talks from Prisma Day 2019"
}
]
},
{
"id": 3,
"email": "ariadne@prisma.io",
"name": "Ariadne",
"posts": [
{
"title": "How to connect to a SQLite database"
},
{
"title": "My first day at Prisma"
}
]
},
]
*/
创建
create
:创建记录- 选项:
data
- 返回对象选项:
select、include
- 选项:
createMany
:创建多个记录- 选项:
data、skipDuplicates
skipDuplicates
:boolean,在插入唯一字段时在冲突中什么都不做。(默认 false)
- 选项:
const user = await prisma.user.create({
data: { email: "alice@prisma.io" },
});
const createMany = await prisma.user.createMany({
data: [
{ name: "Bob", email: "bob@prisma.io" },
{ name: "Bobo", email: "bob@prisma.io" }, // 唯一键重复!
{ name: "Yewande", email: "yewande@prisma.io" },
{ name: "Angelique", email: "angelique@prisma.io" },
],
skipDuplicates: true, // 跳过 'Bobo'
});
查询
1、
findUnique
:唯一条件来获取单个数据库记录- 按 ID
- 按 唯一(unique) 属性
- 选项:
where
- 返回对象选项:
select、include
2、
findFirst
:返回第一个匹配您的条件的记录。- 选项:
distinct、where、cursor、orderBy、skip、take
- 返回对象选项:
select、include
- 选项:
3、
findMany
:返回列表- 选项:
distinct、where、cursor、orderBy、skip、take
- 返回对象选项:
select、include
- 选项:
查询特定字段
// select email,name from user
const getUser: object | null = await prisma.user.findUnique({
where: {
id: 1,
},
select: {
email: true,
name: true,
},
});
- 联合查询
// SELECT u.name,p.title FROM prisma.`User` AS u LEFT JOIN prisma.Post AS p
// ON u.id = p.authorId
const users = await prisma.user.findMany({
select: {
name: true,
posts: {
select: {
title: true,
},
},
},
});
- 分页查询
- skip:跳过前三个,然后返回 4 个
- take:返回特定数量
// 分页查询
// 跳过前三个 1 2 3; 返回 4 5 6 7
const results = await prisma.post.findMany({
skip: 3,
take: 4,
});
更新
update
:更新记录- 选项:
data、where
- 返回对象选项:
select、include
- 选项:
updateMany
:更新多个记录- 选项:
data、where
- 选项:
upsert
:更新或创建记录- 选项:
create、update、where
- 返回对象选项:
select、include
- 选项:
// update
const user = await prisma.user.update({
where: { id: 1 },
data: { email: "alice@prisma.io" },
});
// updateMany
const users = await prisma.user.createMany({
data: [
{ name: "Sonali", email: "sonali@prisma.io" },
{ name: "Alex", email: "alex@prisma.io" },
],
});
// 查找电子邮件地址更新 User 记录,或者如果该 User 记录不存在,则创建该记录:
const upsertUser = await prisma.user.upsert({
where: {
email: "viola@prisma.io",
},
update: {
name: "Viola the Magnificent",
},
create: {
email: "viola@prisma.io",
name: "Viola the Magnificent",
},
});
删除
delete
:删除记录(只能应用于 ID 或unique
属性)- 选项:
where
- 返回对象选项:
select、include
- 选项:
delteMany
:删除多个记录- 选项:
where
- 选项:
// 以下查询会删除特定用户记录并使用 select 返回被删除用户的 name 和 email:
const deleteUser = await prisma.user.delete({
where: {
email: "elsa@prisma.io",
},
select: {
email: true,
name: true,
},
});
count
count()
:统计数量- 选项:
distinct、where、cursor、orderBy、select、skip、take
- 选项:
const c = await prisma.user.count({
select: {
_all: true, // 统计记录的总数
city: true, // 统计非 null city字段的总数
name: true, // 统计非 null name字段的总数
},
});
关系查询
- 关系嵌套查询
// 1. 返回 user用户对应自己的 posts 表信息.
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
include: {
posts: true,
},
});
// 2. 深嵌套
// 返回 user + posts + categories
const user = await prisma.user.findMany({
include: {
posts: {
include: {
categories: true,
},
},
},
});
- 查询特定字段
// 返回 user.name, posts.title
const getUser = await prisma.user.findUnique({
where: {
id: 19,
},
select: {
name: true,
posts: {
select: {
title: true,
},
},
},
});
- 关系嵌套写入
- 创建 User 用户时同时创建 Post,并自动传递作者 ID。
async function main() {
let user: Prisma.UserCreateInput;
user = {
email: "elsa@prisma.io",
name: "Elsa Prisma",
posts: {
create: {
title: "Include this post!",
},
},
include: {
posts: true, // 返回对象包含 posts 对象
},
};
// 将 'user' 对象传递到查询中
const createUser = await prisma.user.create({ data: user });
}
connect 连接记录
- 连接记录什么意思呢?
- 表和表的关联,例如
user
表的用户 ID 字段与Post
表的作者 ID 字段相互连接。 - 简单点说就是,
Post.authorId === User.id
- 表和表的关联,例如
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorId], references: [id])
authorId Int
}
- 连接现有记录
connect
- 例:创建一个新用户,并把
Post
中的 id 为 8 9 10 的 作者 ID 更改为他。
- 例:创建一个新用户,并把
const user = await prisma.user.create({
data: {
email: "vlad@prisma.io",
posts: {
connect: [{ id: 8 }, { id: 9 }, { id: 10 }],
},
},
include: {
posts: true, // 包括返回对象中的所有帖子
},
});
- 连接现有记录
connect
- 将现有帖子(
id:11
)连接到现有用户(id:9
) - 添加一个新的相关帖子(
title: "My new post title"
)
- 将现有帖子(
const getUser = await prisma.user.update({
where: {
id: 9,
},
data: {
posts: {
connect: {
id: 11,
},
create: {
title: "My new post title",
},
},
},
});
- 连接或创建
connectOrCreate
- 当不清楚记录是否存在时,就用这个。
// 存在 "viola@prisma.io" 则使用,否则就创建新的
const createPost = await prisma.post.create({
data: {
title: "How to make croissants",
author: {
connectOrCreate: {
where: {
email: "viola@prisma.io",
},
create: {
email: "viola@prisma.io",
name: "Viola",
},
},
},
},
include: {
author: true,
},
});
disconnect 断开连接
断开连接什么意思?
- 中断父记录和相关记录之间的连接,但不会删除任一记录。
- 仅在关系是可选的情况下可用。
断开连接
disconnect
// 1.
const updatePost = await prisma.user.update({
where: {
id: 16,
},
data: {
posts: {
disconnect: [{ id: 12 }, { id: 19 }],
},
},
select: {
posts: true,
},
});
// 2. 当为一条记录的时候, 使用 true
// 例如 profile?
const user = await prisma.user.update({
where: { email: "bob @prisma.io" },
data: {
profile: {
disconnect: true,
},
},
});
- 断开所有连接
set:[]
const updateUser = await prisma.user.update({
where: {
id: 16,
},
data: {
posts: {
set: [],
},
},
include: {
posts: true,
},
});
- 删除所有记录
- 删除特定相关记录
// 删除所有
const update = await prisma.user.update({
where: {
id: 11,
},
data: {
posts: {
deleteMany: {},
},
},
});
// 删除所有 "published: false" 的 Post
const update = await prisma.user.update({
where: {
id: 11,
},
data: {
posts: {
deleteMany: {
published: false,
},
},
},
});
// 特定用户
const update = await prisma.user.update({
where: {
id: 6,
},
data: {
posts: {
deleteMany: [{ id: 7 }],
},
},
});
更新或创建
- update
// 将关联用户ID为6的所有, Post 的 published 值变为 false
const update = await prisma.user.update({
where: {
id: 6,
},
data: {
posts: {
updateMany: {
where: {
published: true,
},
data: {
published: false,
},
},
},
},
});
- upset
// 更新或创建 PostID 为 6 的所关联的 用户信息
const update = await prisma.post.update({
where: {
id: 6,
},
data: {
author: {
upsert: {
create: {
email: "bob@prisma.io",
name: "Bob the New User",
},
update: {
email: "bob@prisma.io",
name: "Bob the existing user",
},
},
},
},
});
- createMany
const user = await prisma.user.update({
where: {
id: 9,
},
data: {
posts: {
createMany: {
data: [{ title: "My first post" }, { title: "My second post" }],
},
},
},
});
关联过滤器
some
:至少有一个none
:否定(取反)every
:一个都没有
操作符:gt、lt、gte、lte(大于、小于、大于等于、小于等于)
// 返回没有文章的用户
const usersWithZeroPosts = await prisma.user.findMany({
where: {
posts: {
none: {},
},
},
});
// 返回至少有一篇文章的用户
const usersWithSomePosts = await prisma.user.findMany({
where: {
posts: {
some: {},
},
},
});
// 返回 `views`不超过100, `likes`小于等于 50 的
const users = await prisma.user.findMany({
where: {
posts: {
none: {
views: {
gt: 100,
},
},
every: {
likes: {
lte: 50,
},
},
},
},
});
is
isNot
// 名字不是"Bob", 年龄大于 40
const users = await prisma.post.findMany({
where: {
author: {
isNot: {
name: "Bob",
},
is: {
age: {
gt: 40,
},
},
},
},
});
过滤条件
- 不区分大小写
mode: 'insensitive'
- 仅支持 PostgreSQL 和 MongoDB 连接器
const users = await prisma.user.findMany({
where: {
email: {
endsWith: "prisma.io",
mode: "insensitive", // Default value: default
},
},
});
not
in:[]
、notIn:[]
- gt、lt、gte、lte、ne(大于、小于、大于等于、小于等于、不等于)
contains
:模糊查询startsWith
:匹配开头endsWith
:匹配结尾
const result = await prisma.user.findMany({
where: {
name: { not: "Eleanor" },
id: { in: [22, 91, 14, 2, 5] },
id: { notIn: [22, 91, 14, 2, 5] },
},
});
const result = await prisma.post.count({
where: {
content: {
contains: "databases",
},
},
});
运算符
- AND:所有条件必须返回
true
。 - NOT:所有条件必须返回
false
。 - OR:至少一个条件必须返回
true
。
// email 以 "prisma.io" 或 "gmail.com" 结尾,但不以 "hotmail.com" 结尾
const result = await prisma.user.findMany({
where: {
OR: [
{
email: {
endsWith: "prisma.io",
},
},
{ email: { endsWith: "gmail.com" } },
],
NOT: {
email: {
endsWith: "hotmail.com",
},
},
},
select: {
email: true,
},
});
聚合、分组和汇总
- 聚合
aggregate
// 求年龄平均值
const aggregations = await prisma.user.aggregate({
_avg: {
age: true,
},
});
// 与过滤结合起来
const aggregations = await prisma.user.aggregate({
_avg: {
age: true,
},
where: {
email: {
contains: "prisma.io",
},
},
orderBy: {
age: "asc",
},
take: 10,
});
console.log("Average age:" + aggregations._avg.age);
- 分组
// 返回每个国家的个人资料浏览总数
const groupUsers = await prisma.user.groupBy({
by: ["country"],
_sum: {
profileViews: true,
},
});
/*
;[
{ country: 'Germany', _sum: { profileViews: 126 } },
{ country: 'Sweden', _sum: { profileViews: 0 } },
]
*/
原始数据库访问
MongoDB 不支持
const email = "emelie@prisma.io";
const result =
await prisma.$queryRaw`SELECT * FROM User WHERE email = ${email}`;
const result = await prisma.$queryRaw(
Prisma.sql`SELECT * FROM User WHERE email = ${email}`
);