prisma2.0和nexus搭建graphql后端(1)—prisma2.0
前言
prisma出了2个大版本,两者不大相同,这里只讲prisma2。 由于之前prisma1集成比较高,导致我把prisma理解为一个graphql服务框架,是错误的。**Prisma是一种数据库工具包,可简化数据库访问,Prisma Client仅“负责”向数据库发送查询。**因此可以将其与您选择的任何HTTP服务器库或Web框架结合使用。您可以使用Prisma工具构建GraphQL或REST API,或者作为全栈应用程序的一部分-结合Prisma的程度取决于您。
- restful prisma可以和http服务框架结合生成restful框架
- graphql 使用Prisma,您可以构建连接到数据库的GraphQL服务器。 Prisma与您使用的GraphQL工具完全无关。nexus 是一个集成了prisma框架的GraphQL应用程序框架。
Prisma Labs团队是Prisma工程团队其他成员的独立组成部分,致力于开发与Prisma数据库工具不直接相关的开源工具。Prisma Labs目前致力于将大部分时间用于Nexus,以期使其成为构建GraphQL服务器的成熟后端框架。也是本文下面要讲的部分。
prisma2.0
1 什么是prisma
prisma官网:https://www.prisma.io/
prisma是一个开源的数据库工具包。它取代了传统的ORM,并使用针对TypeScript和Node.js的自动生成的查询生成器使数据库访问变得容易。
prisma包括3个部分:
- prisma client:自动生成的类型安全的Node.js和TypeScript查询构建器
- prisma migrate:声明式数据建模和迁移系统
- prisma studio:GUI查看和编辑数据库中的数据
2 工作原理
每个使用prisma的项目都以一个prisma.schema文件开始。prisma.schema文件它以一直直观的数据建模语句定义应用程序模型,还包括了数据库连接和定义了一个生成器。数据模型表示基础数据库中的表,为Prisma Client API中的查询提供基础。
下面是一个prisma schema文件例子
datasource db {provider = "postgresql"url = env("DATABASE_URL")
} //这里定义了数据源,指定了数据库如何连接,可以通过环境变量,它会自动从和这个文件同名的.env文件中自动读取环境变量
generator client {provider = "prisma-client-js"
} // 这里表示要生成一个prisma client// 下面的数据模型 data model
model Post {id Int @id @default(autoincrement())title Stringcontent String?published Boolean @default(false)author User? @relation(fields: [authorId], references: [id])authorId Int?
}
model User {id Int @id @default(autoincrement())email String @uniquename String?posts Post[]
}
定义数据模型后,您可以生成Prisma Client,它将公开CRUD和已定义模型的查询。可以通过命令安装npm install @prisma/client
然后通过prisma generate
生成prisma client 的代码,在.prisma/client
文件夹,这里包括了自动生成的prisma client 。如果你改了data model ,需要收到运行generate命令,然后prisma client会自动更新。
Prisma Client生成后,您可以导入代码并将查询发送到数据库。代码大致如下:
import {PrismaClient} from '@prisma/client'const prisma = new PrismaClient()// A `main` function so that you can use async/await
async function main() {// ... you will write your Prisma Client queries here// createconst post = await prisma.post.create({data: {title: "Prisma makes databases easy",author: {connect: {email: "maria@prisma.io"},}}})const user = await prisma.user.create({data: {name: "Nancy1",email: "nancy1@prisma.io",Post: {create: {title: "Join us for Prisma Day 2020"}}}})// updateconst post = await prisma.post.update({where: {id: 2},data: {published: true}})// deleteconst deleteUser = await prisma.user.delete({where: {email: "sarah@prisma.io"}})// get listconst allUsers = await prisma.user.findMany({include: {Post: true}})// find oneconst user = await prisma.user.findOne({where: {email: "sarah@prisma.io"}}).posts()// filterconst filteredPosts = await prisma.post.findMany({where: {OR: [{title: {contains: "prisma"}},{content: {contains: "prisma"}}]}})
}
prisma 工作流有如下两种:
(1) SQL migrations and introspection :
- 使用SQL手动调整数据库架构
- 利用命令
prisma introspect
去更新你的prisma schema 文件的data model - 再利用
prisma generate
去更新生产你的prisma client - 最后使用prisma client 在代码里去访问数据库
(2) Prisma Migrate: - 人工调整你的prisma schema data model
- 利用
prisma migrate save --experimental
生产/prisma/migratons文件 prisma migrate up --experimental
命令去更新你的数据库- 再利用
prisma generate
去更新生产你的prisma client - 最后使用prisma client 在代码里去访问数据库
Prisma引擎是数据库的直接接口,任何更高级别的接口始终通过引擎层与数据库通信。
3 核心概念
3.1 prisma schema
prisma schem 包括3个部分:
- Data source 定义了数据源,下面是几个常见数据源的几个定义方式
datasource postgresql {provider = "postgresql"url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public"
}datasource mysql {provider = "mysql"url = "mysql://johndoe:mypassword@localhost:5432/mydb"
}datasource sqlite {provider = "sqlite"url = "file:./dev.db"
}
可以使用环境变量 通过创建具有以下内容的.env文件。请注意,该文件必须与schema.prisma文件位于同一目录中,以自动选择Prisma CLI。
datasource postgresql {provider = "postgresql"url = env("DATABASE_URL")
}
- Generators
generator client {provider = "prisma-client-js" //描述要使用的生成器。这可以指向实现生成器的文件,也可以直接指定内置生成器output = "node_modules/@prisma/client" // 确定生成的客户端的位置,了解更多信息。默认值:node_modules / @ prisma / clientbinaryTargets = ["native"] // 指定将在其上运行Prisma Client的操作系统,以确保查询引擎的二进制兼容性。默认值:本机
}
- Data model
数据模型定义定义您的应用程序模型(也称为Prisma模型)。这些模型代表您的应用程序域的实体,并映射到数据库中的表。
- model vs enum
enum Role {USERADMIN
}
model User {id Int @id @default(autoincrement())role Role @default(USER)
}
model 属性
name | 数据库表示的含义 | 描述 | 例子 |
---|---|---|---|
@id | primary key | 在模型上定义一个单字段ID |
id Int @id
|
@@id | primary key | 在模型上定义多个单字段ID |
@@id([title, author]) )
|
@default | default | 定义此字段的默认值。 @default将表达式作为参数。 |
role Boolean @default(false)
|
@unique | unique | 为该字段定义唯一约束。 |
email String @unique
|
@@unique | unique | 为指定字段定义复合唯一约束。 |
@@unique([title, author])
|
@@index | Index | 字段引用列表定义索引 |
@@index([title, author])
|
@relation | FOREIGN KEY / REFERENCES | 定义有关关系的元信息 |
author User @relation(fields: [authorId], references: [id])
|
@map | 将字段名称从Prisma模式映射到其他列名称 | @map(_ name: String) | |
@@map | 将字段名称从Prisma模式映射到其他列名称 | @@map(_ name: String) | |
@updatedAt | 自动存储上次更新记录的时间 |
createdAt DateTime @update
|
|
autoincrement() | Id自增 |
id Int @id @default(autoincrement())
|
|
cuid() | 根据cuid规范生成全局唯一标识符 |
id String @id @default(cuid())
|
|
uuid() | 根据UUID规范生成全局唯一的标识符 |
id String @id @default(uuid())
|
|
new() | 设置创建记录的时间的时间戳 | ||
dbgenerated() | 表示无法在Prisma模式中表示的默认值。内省后才可用 |
- Scalar types 表量类型: String Boolean Int Float DateTime(2020-03-19T14:21:00+0200) Json
- 类型修饰符 []:将字段设为列表 ?:将字段设为可选 请注意,您不能在同一字段上组合列表和可选修饰符
- relations关系
(1)一对一
model User {id Int @id @default(autoincrement())profile Profile?
}
model Profile {id Int @id @default(autoincrement())user User @relation(fields: [userId], references: [id])userId Int // relation scalar field (used in the `@relation` attribute above)
}
(2)一对多
model User {id Int @id @default(autoincrement())email String @uniquerole Role @default(USER)posts Post[]
}
model Post {id Int @id @default(autoincrement())title Stringauthor User @relation(fields: [authorId], references: [id])authorId Int // relation scalar field (used in the `@relation` attribute above)
}
(3)多对多
显式的多对多关系
model Post {id Int @id @default(autoincrement())title Stringcategories CategoriesOnPosts[]
}
model Category {id Int @id @default(autoincrement())name Stringposts CategoriesOnPosts[]
}
model CategoriesOnPosts {post Post @relation(fields: [postId], references: [id])postId Int // relation scalar field (used in the `@relation` attribute above)category Category @relation(fields: [categoryId], references: [id])categoryId Int // relation scalar field (used in the `@relation` attribute above)@@id([postId, categoryId])
}
隐式的多对多关系
model Post {id Int @id @default(autoincrement())categories Category[] @relation(references: [id])
}
model Category {id Int @id @default(autoincrement())posts Post[] @relation(references: [id])
}
3.2 prisma client
Prisma Client为多个CRUD查询提供了开箱即用的支持。 CRUD代表:Creat read update Delete
Prisma Client中提供以下CRUD查询:
- findOne ——findOne查询使您可以按ID或另一个唯一属性检索单个数据库记录。您可以使用select和include选项来确定应在返回的对象上包括哪些属性。select 和include不能同时存在,两者都是规定返回值。
const user = await prisma.user.findOne({where: {email: "nancy1@prisma.io"},select: {id: true, email: true,Post:true},// include: {Post: true}})
- findMany ——findMany查询返回记录列表。您可以使用select和include选项来确定返回的对象应包括哪些属性。您还可以对列表进行分页,过滤和排序。
(1)where 查询
const user = await prisma.user.findMany({where: { name: 'Alice' },select: {id: true, email: true,Post:true},// include: {Post: true}
})
(2) 过滤
// AND OR NOT 结合多个过滤条件
// 过滤条件 euqals not in notin It(<) Ite(<=) gt(>) gte(>=) contains startsWith endsWith
const result = await prisma.post.findMany({where: {OR: [{title: {contains: 'Prisma',},}],NOT: {title: {contains: 'SQL',},},},
})
// Prisma Client提供以下运算符,用于筛选一对多关系: some every none
const result = await prisma.user.findMany({where: {post: {every: {published: true}some: {content: {contains: "Prisma"}}}}}// 用include filter
const result = await prisma.user.findMany({where: {email: {contains: 'prisma.io',},},include: {Post: {where: {published: false,},},},
})
// 用select filter
const result = await prisma.user.findMany({where: {email: {contains: 'prisma.io',},},select: {Post: {where: {published: false,},select: {title: true,},},},
})
- create :创建查询将创建一个新的数据库记录。您可以使用select和include选项来确定应在返回的对象上包括哪些属性 data include select
const user = await prisma.user.create({data: {name: "Nancy1",email: "nancy1@prisma.io",Post: {create: {title: "Join us for Prisma Day 2020"}// connect: {id: 1},}}})
- update:更新查询更新现有的数据库记录。您可以使用select和include选项来确定应在返回的对象上包括哪些属性。data where select include
const user = await prisma.user.update({where: { id: 1 },data: { email: 'alice@prisma.io' },
})
- updateMany: updateMany查询批量更新一批现有数据库记录,并返回已删除记录的数量。您可以过滤要更新的记录列表 data where
const updatedUserCount = await prisma.user.updateMany({where: { name: 'Alice' },data: { name: 'ALICE' },
})
- upsert:upsert查询更新现有记录或创建新的数据库记录。您可以使用select和include选项来确定应在返回的对象上包括哪些属性。 create update where select include
const user = await prisma.user.upsert({where: { id: 1 },update: { email: 'alice@prisma.io' },create: { email: 'alice@prisma.io' },
})
- delete:删除查询删除现有的数据库记录。即使删除记录,删除仍然返回已删除的对象。您可以使用select和include选项来确定应在返回的对象上包括哪些属性。 where select include
const user = await prisma.user.delete({where: { id: 1 },
})
- deleteMany:deleteMany查询将批量删除一批现有的数据库记录,并返回已删除记录的数量。您可以过滤要删除的记录列表。 where
const deletedUserCount = await prisma.user.deleteMany({where: { name: 'Alice' },
})
- count:在PrismaClient实例上的任何模型属性上使用count()方法可返回一定数量的可用记录。您可以过滤要计数的记录列表。
const result = await prisma.user.count({where: {post: {some: {published: true,},},},
})
- raw 原生数据查询
const result = await prisma.raw('SELECT * FROM User;')
- connect() disconnect() 连接数据库和断开
const prisma = new PrismaClient()
await prisma.connect()
main().catch(e => {throw e}).finally(async () => {await prisma.disconnect()})
- logging 您可以通过在PrismaClient构造函数中配置不同的日志级别来查看Prisma Client发送到数据库的生成的数据库查询以及警告和其他信息。您可以通过log选项执行此操作:
const prisma = new PrismaClient({log: ['query', 'info', 'warn'],
});
// query:记录由Prisma Client API调用生成的SQL查询
// info:记录常规信息
// 警告:记录警告
- debug 您可以通过DEBUG环境变量在Prisma Client中启用调试输出。它接受两个名称空间来打印调试输出:
export DEBUG="prisma-client,engine"
- errorFormat 定义错误格式 minimal colorless pretty(默认)
3.3 prisma migrate
Prisma Migrate是一种工具,可让您更改数据库架构,例如通过创建新表或向现有表添加列。这些更改称为架构迁移。 Prisma Migrate可通过prisma migration命令作为Prisma CLI的一部分使用。
3.4 prisma instrospection
您可以使用Prisma CLI自检数据库,以便在Prisma模式中生成数据模型。需要数据模型来生成Prisma Client。用反映当前数据库模式的数据模型填充Prisma schema。
3.5 prisma cli
安装 npm install @prisma/cli --save-dev npm install -g @prisma/cli
prisma studio --experimental
// Prisma Studio是数据库的可视编辑器
4. prisma 实践
4.1 加入到已有的项目中
- 先决条件 项目中有package.json 机器安装了node 现有的pg数据库并且有个表
- 第一步 安装prisma
yarn add @prisma/cli --dev
然后初始化项目prisma init
会生成一个包括schema.prisma和.env文件的文件夹prisma - 要连接数据库,修改 schema.prisma文件的datasource 然后执行
prisma introspect
命令根据前面的数据库生成data modal - 安装prisma client
yarn add @prisma/client
prisma generate
执行命令生产prisma client库 - 新建你的查询 新建index.ts文件 ts-node index.ts运行文件
import { PrismaClient } from "@prisma/client"
const prisma = new PrismaClient()
async function main() {const allUsers = await prisma.user.findMany()console.log(allUsers)
}
main().catch(e => {throw e}).finally(async () => {await prisma.disconnect()})
4.2 从一个新项目开始
- mkdir hello-prisma cd hello-prisma
- npm init -y npm install @prisma/cli typescript ts-node @types/node --save-dev
- 创建tsconfig.json文件
{"compilerOptions": {"sourceMap": true,"outDir": "dist","strict": true,"lib": ["esnext"],"esModuleInterop": true}
}
- prisma init 会生成一个包括schema.prisma和.env文件的文件夹prisma
- 要连接数据库,修改 schema.prisma文件的datasource 然后执行
prisma introspect
命令根据前面的数据库生成data modal - 安装prisma client
yarn add @prisma/client
prisma generate
执行命令生产prisma client库 - 新建你的查询 新建index.ts文件 ts-node index.ts运行文件
4.2 从一个新项目开始 利用 prisma migrate
- mkdir hello-prisma cd hello-prisma
- npm init -y npm install @prisma/cli typescript ts-node @types/node --save-dev
- 创建tsconfig.json文件
{"compilerOptions": {"sourceMap": true,"outDir": "dist","strict": true,"lib": ["esnext"],"esModuleInterop": true}
}
- prisma init 会生成一个包括schema.prisma和.env文件的文件夹prisma
- 要连接数据库,修改 schema.prisma文件的datasource 然后修改文件里的data model
- npx prisma migrate save --name init --experimental
npx prisma migrate up --experimental 执行这两个命令回去创建(修改)数据表 - 安装prisma client
yarn add @prisma/client
prisma generate
执行命令生产prisma client库 - 新建你的查询 新建index.ts文件 ts-node index.ts运行文件
nexus
prisma+nexus
其他好用的工具推荐
prisma2.0和nexus搭建graphql后端(1)—prisma2.0相关推荐
- redis5.0.5版本搭建集群
redis5.0.5版本搭建集群 安装redis5.0.5版本 将redis5.0.5解压 sudo tar -zxcf re ...
- 创业公司 如果让你作技术负责人,你会如何从0搭建公司后端技术栈
创业公司 如果让你作技术负责人,你会如何从0搭建公司后端技术栈 文章目录 创业公司 如果让你作技术负责人,你会如何从0搭建公司后端技术栈 各系统组件选型 1.项目管理/Bug管理/问题管理 2.DNS ...
- 教你从0到1搭建秒杀系统-订单异步处理
前面几篇我们从限流角度,缓存角度来优化了用户下单的速度,减少了服务器和数据库的压力.这些处理对于一个秒杀系统都是非常重要的,并且效果立竿见影,那还有什么操作也能有立竿见影的效果呢?答案是下单的异步处理 ...
- 教你从0到1搭建秒杀系统-限流
本文是秒杀系统的第二篇,主要讲解接口限流措施.接口限流其实定义也非常广,接口限流本身也是系统安全防护的一种措施,在面临高并发的请购请求时,我们如果不对接口进行限流,可能会对后台系统造成极大的压力,尤其 ...
- CentOS 初体验十六:阿里云安装Nexus搭建Maven私有仓库
转载请注明出处http://blog.csdn.net/zhaoyanjun6/article/details/79198469 本文出自[赵彦军的博客] 简介 mavenCentral 是最早的 m ...
- 使用Nexus搭建私有Nuget仓库
前言 Nuget是ASP .NET Gallery的一员,是免费.开源的包管理工具,专注于在.Net / .Net Core应用开发过程中第三方组件库的管理,相对于传统单纯的dll引用要方便.科学得多 ...
- centos利用nexus搭建局域网docker私有仓库
centos利用nexus搭建局域网docker私有仓库 1.官网下载nexus oss版本 https://sonatype-download.global.ssl.fastly.net/repos ...
- 程序员如何从0到1搭建自己的技术博客
记得刚毕业参加工作时,每天早上到公司后,都会逛逛博客园,看一下各位大牛前辈写的文章,也许是兴趣使然,当时就特别想搭建一个属于自己的独立的技术博客. 时间就是过的这么快,转眼间这么多年过去了,我的这个梦 ...
- 搭建前后端分离主流项目完整步骤——在线教育系统(阿里云服务器部署上线)
前言: 需要源码评论或私我 项目技术栈如下图所示: 本次博客分前后端+部署服务器三个步骤来写 先来看看实现效果: 在线教育系统完整三步骤 前言: 一.后端技术栈 1.ssm+mysql: (1)map ...
- Nexus 搭建私有镜像仓库
Nexus 搭建私有镜像仓库 说明 国内网络环境下直接使用默认的 npm 下载资源过慢,所以很多文章中都建议将 npm 的 registry 切换为 淘宝的 npm 镜像,如下 npm config ...
最新文章
- # Ubuntu 配置自带vnc桌面共享
- switch的case使用数组C语言,使用常量数组的元素作为switch语句中的case
- 拆分命令_在MongoDB分片集群中拆分数据块chunks
- Matlab学习笔记——文件的打开与关闭
- PyTorch 之 DataLoader
- javascript日期时间操作总结
- 基于对象和面向对象编程范式辨析和主流编程语言中的应用
- rtmp推流直播流程
- QPainter 的状态保存与恢复
- 计算机辅助项目管理有关论文,项目管理论文
- cloudstack基础知识
- 金蝶K3案例教程目录2022
- 记录一些比较常用的简单jsp模板
- api64 gta5缺少steam_GTA5无法启动此程序,因为计算机中丢失steam_api64.dll 游戏打不来 现实这个,win7 64位....
- 【神经网络架构】Pyramid Convolution(金字塔卷积模块)论文笔记
- 京东云主机使用-搭建简单网页(macOS)
- error: The requested URL returned error: 401 Unauthorized while accessing
- 第十三届蓝桥杯省赛C++B组题解
- 滴滴云服务器搭建网站的一键脚本,一键搭建流控脚本 一键搭建云免流服务器...
- 微信小程序--js中string转换为number
热门文章
- 如何产生JIC文件(sof+ELF=jic)
- 什么是AOP(面向切片编程)
- 数学中倒三角:梯度;正三角:拉普拉斯
- tampermonkey(油猴)——去除烦人的百度搜索广告
- ListFields
- 鸿蒙灵根都有哪些,盘点鸿蒙先天十大灵根,你知道哪一个?
- 圣诞节来了,雪花纷飞的CSS3动画,还不首页用起来
- Python学习笔记(5)-集成开发环境IDLE的使用与调试
- php在线图片签名,ElementUi+Vue+Php+fpdf+fpdi 实现文档在线签订(图片水印、手写签名)...
- 皮肤测试小软件有哪些,【皮肤测试小程序】皮肤测试小程序有什么功能呢?