Prisma 知识点归纳(二)增删改查以及关系查询汇总 1W3字大章 2023
系列 - Prisma 知识点归纳
目录
该文档的基础是建立在学过关系型数据库的基础上,并且以下内容是根据 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 generate1 基本使用
1.1 查询选项
- 选项
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": "[email protected]",
"name": "Alice",
"posts": [
{
"title": "Watch the talks from Prisma Day 2019"
}
]
},
{
"id": 3,
"email": "[email protected]",
"name": "Ariadne",
"posts": [
{
"title": "How to connect to a SQLite database"
},
{
"title": "My first day at Prisma"
}
]
},
]
*/1.2 创建
create:创建记录- 选项:
data - 返回对象选项:
select、include
- 选项:
createMany:创建多个记录- 选项:
data、skipDuplicatesskipDuplicates:boolean,在插入唯一字段时在冲突中什么都不做。(默认 false)
- 选项:
const user = await prisma.user.create({
data: { email: "[email protected]" },
});
const createMany = await prisma.user.createMany({
data: [
{ name: "Bob", email: "[email protected]" },
{ name: "Bobo", email: "[email protected]" }, // 唯一键重复!
{ name: "Yewande", email: "[email protected]" },
{ name: "Angelique", email: "[email protected]" },
],
skipDuplicates: true, // 跳过 'Bobo'
});1.3 查询
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,
});1.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: "[email protected]" },
});
// updateMany
const users = await prisma.user.createMany({
data: [
{ name: "Sonali", email: "[email protected]" },
{ name: "Alex", email: "[email protected]" },
],
});
// 查找电子邮件地址更新 User 记录,或者如果该 User 记录不存在,则创建该记录:
const upsertUser = await prisma.user.upsert({
where: {
email: "[email protected]",
},
update: {
name: "Viola the Magnificent",
},
create: {
email: "[email protected]",
name: "Viola the Magnificent",
},
});1.5 删除
delete:删除记录(只能应用于 ID 或unique属性)- 选项:
where - 返回对象选项:
select、include
- 选项:
delteMany:删除多个记录- 选项:
where
- 选项:
// 以下查询会删除特定用户记录并使用 select 返回被删除用户的 name 和 email:
const deleteUser = await prisma.user.delete({
where: {
email: "[email protected]",
},
select: {
email: true,
name: true,
},
});1.6 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字段的总数
},
});2 关系查询
- 关系嵌套查询
// 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: "[email protected]",
name: "Elsa Prisma",
posts: {
create: {
title: "Include this post!",
},
},
include: {
posts: true, // 返回对象包含 posts 对象
},
};
// 将 'user' 对象传递到查询中
const createUser = await prisma.user.create({ data: user });
}2.1 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: "[email protected]",
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- 当不清楚记录是否存在时,就用这个。
// 存在 "[email protected]" 则使用,否则就创建新的
const createPost = await prisma.post.create({
data: {
title: "How to make croissants",
author: {
connectOrCreate: {
where: {
email: "[email protected]",
},
create: {
email: "[email protected]",
name: "Viola",
},
},
},
},
include: {
author: true,
},
});2.2 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 }],
},
},
});2.3 更新或创建
- 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: "[email protected]",
name: "Bob the New User",
},
update: {
email: "[email protected]",
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" }],
},
},
},
});2.4 关联过滤器
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,
},
},
},
},
});isisNot
// 名字不是"Bob", 年龄大于 40
const users = await prisma.post.findMany({
where: {
author: {
isNot: {
name: "Bob",
},
is: {
age: {
gt: 40,
},
},
},
},
});2.5 过滤条件
- 不区分大小写
mode: 'insensitive'- 仅支持 PostgreSQL 和 MongoDB 连接器
const users = await prisma.user.findMany({
where: {
email: {
endsWith: "prisma.io",
mode: "insensitive", // Default value: default
},
},
});notin:[]、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",
},
},
});2.6 运算符
- 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,
},
});3 聚合、分组和汇总
- 聚合
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 } },
]
*/4 原始数据库访问
MongoDB 不支持
const email = "[email protected]";
const result =
await prisma.$queryRaw`SELECT * FROM User WHERE email = ${email}`;
const result = await prisma.$queryRaw(
Prisma.sql`SELECT * FROM User WHERE email = ${email}`
);