Prisma的简介和使用

Prisma的简介和使用

什么是 Prisma

官网介绍

We simplify query caching,so you don’t have to know how it works

We simplify database subscriptions,so you don’t have to worry about them

We simplify databse migrations,so you don’t have to explain them

We simplify readable date models,so you don’t have to figure out how

We simplify database queries,so you don’t have to manage it

We simplify connecting pooling,so you don’t have to get a PhD in it

翻译过来就是:

我们简化了查询缓存,因此您不必了解它是如何工作的。

我们简化了数据库订阅,因此您不必担心它们。

我们简化了数据库迁移,因此您不必解释它们。

我们简化了可读的日期模型,因此您不必弄清楚如何实现。

我们简化了数据库查询,因此您不必管理它。

我们简化了连接池,因此您不必获得博士学位。

关于 ORM(Object/Relational Mapping),简单来说就是一个可以像操作对象一样操作数据库的工具

就好像 MongoDB 是数据库,Mongoose 是 MongoDB 的 ORM

Prisma 更加强大,它使用更加方便,又支持 PostgreSQL、MySQL、MongoDB、SQL Server和SQLite 等多个数据库

如果要学习 Prisma ,最简单的方法就是去官网看一下它的教学

我相信只要你看完以上几个视频,对 Prisma 的已经会用了,之后叠加 AI 辅助,就能写出你想要的增删改查了

Prisma 组成

Prisma 的产品有很多,其中 Prisms ORM 是我们使用的最最关注的

Prisma ORM是一个基于 Nodejs 和 TypeScript 的 ORM,由于其直观的数据模型、自动迁移、类型安全和自动完成功能,它在处理数据库时解锁了开发人员的新体验。

除此之外,还有 Prisma Optimize、Prisma Accelerate、Prisma Pules、以及新出的Prisma Postgres

  • Prisma Optimize:分析查询、生成见解并提供建议以加快数据库查询速度
  • Prisma Accelerate:全局数据库缓存,具有可扩展的连接池,可加快查询速度
  • Prisma Pules:允许使用类型安全的模型流实时响应数据库更改
  • Prisma Postgres:托管的 PostgreSQL 服务

其中我们最关注的 Prisms ORM 由以下工具组成:

  • Prisma Client:自动生成且类型安全的Node.js和TypeScript查询构建器
  • Prisma Migrate:声明式数据建模和迁移系统
  • Prisma Studio:用于查看和编辑数据库中的数据的可视化工具

Prisma 要学习的点

因为 Prisma 要做的是跨数据库,所以它分为两部分,一部分是对数据库的连接以及定义 Schema,二是由 Prisma Client 做的增删改查

第一部分做的是兼容各个数据库的不同,以 Prisma ORM 的标准来定义 Schema。简单说就是 数据类型的映射,例如 Prisma ORM 的 String 在 SQLite 里是 TEXT,在 PostgreSQL 就是text,而在 MySQL 里是VARCHAR(191)

而且定义 Schema 后的表的关系也是 Prisma 的自定义的标准

第二部分就是Prisma Client 做的增删改查,看文档一目了然

当你修改 Schema (就是你定义的表)后,你需要将其迁移到数据库中,命令为 prisma migrate dev --name xxx

Prisma 实操

第一步:下载 prisma

pnpm i prisma -D

使用 pnpm prisma 命令能获得 Prisma 的各种介绍以及命令行的使用

Prisma is a modern DB toolkit to query, migrate and model your database (https://www.prisma.io)

Usage

  $ prisma [command]

Commands

            init   Setup Prisma for your app
        generate   Generate artifacts (e.g. Prisma Client)
              db   Manage your database schema and lifecycle
         migrate   Migrate your database
          studio   Browse your data with Prisma Studio
        validate   Validate your Prisma schema
          format   Format your Prisma schema

Flags

     --preview-feature   Run Preview Prisma commands

Examples

  Setup a new Prisma project
  $ prisma init

  Generate artifacts (e.g. Prisma Client)
  $ prisma generate

  Browse your data
  $ prisma studio

  Create migrations from your Prisma schema, apply them to the database, generate artifacts (e.g. Prisma Client)
  $ prisma migrate dev

  Pull the schema from an existing database, updating the Prisma schema
  $ prisma db pull

  Push the Prisma schema state to the database
  $ prisma db push

第二步:初始化

pnpm prisma init

这一步会在根目录下创建 prisma 文件,并在其中创建 schema.prisma 文件

第三步:添加 schma.prisma 以及.env 中的数据库地址

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL")
}
DATABASE_URL="postgresql://username:password@localhost:5432/mydb?schema=public"

第四步:下载@prisma/client 客户端、vscode 下载 prisma 插件

pnpm i @prisma/client

第五步:回到 schma.prisma 写 model

即定义 User 模型

model UserApiLimit {
  id        String      @id @default(cuid())
  userId    String   @unique
  count     Int      @default(0)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

第七步:同步数据库

将 prisma 模型同步到数据库

pnpm prisma db push

如果是一个已经有数据的项目,就不能使用这个命令,而是用 prisma migrate 迁移

第八步:生成 Prisma Client

前面同步数据库时,已经执行了 prisma generate。所以现在不需要再次执行了,但是一旦 Prisma Schema 文件发生了变动,比如修改了模型,就需要再来执行下这个命令,重新生成 Prisma Client。

pnpm prisma generate

第九步:在线查看数据库

pnpm prisma studio

第十步:@prisma/client 链接数据库

import { PrismaClient } from '@prisma/client'

declare global {
  var prisma: PrismaClient | undefined
}

const prisma = global.prisma || new PrismaClient()

if (process.env.NODE_ENV !== 'production') global.prisma = prisma

export default prisma

Prisma Schema

Prisma Schema 是在最大程序上贴近数据库结构描述的基础上,对关联关系进行进一步抽象

https://camo.githubusercontent.com/5dc1a4d1b53d9b73c71228619cb9cf8ec34dfeef0c2378c7700429e771d42c93/68747470733a2f2f7a332e617831782e636f6d2f323032312f31302f31372f3559775a6f462e706e67

字段由下面四种描述组成:

  • 字段名。
  • 字段类型。
  • 可选的类型修饰。
  • 可选的属性描述。
model Tag {
  name String? @id
}

在这个描述里,包含字段名 name、字段类型 String、类型修饰 ?、属性描述 @id

prisma Client CRUD

使用 create 创建一条记录:

const user = await prisma.user.create({
  data: {
    email: "elsa@prisma.io",
    name: "Elsa Prisma",
  },
});

使用 createMany 创建多条记录:

const createMany = await prisma.user.createMany({
  data: [
    { name: "Bob", email: "bob@prisma.io" },
    { name: "Bobo", email: "bob@prisma.io" }, // Duplicate unique key!
    { name: "Yewande", email: "yewande@prisma.io" },
    { name: "Angelique", email: "angelique@prisma.io" },
  ],
  skipDuplicates: true, // Skip 'Bobo'
});

使用 findUnique 查找单条记录:

const user = await prisma.user.findUnique({
  where: {
    email: "elsa@prisma.io",
  },
});

对于联合索引的情况:

model TimePeriod {
  year    Int
  quarter Int
  total   Decimal

  @@id([year, quarter])
}

需要再嵌套一层由 _ 拼接的 key:

const timePeriod = await prisma.timePeriod.findUnique({
  where: {
    year_quarter: {
      quarter: 4,
      year: 2020,
    },
  },
});

使用 findMany 查询多条记录:

const users = await prisma.user.findMany();

可以使用 SQL 中各种条件语句,语法如下:

const users = await prisma.user.findMany({
  where: {
    role: "ADMIN",
  },
  include: {
    posts: true,
  },
});

使用 update 更新记录:

const updateUser = await prisma.user.update({
  where: {
    email: "viola@prisma.io",
  },
  data: {
    name: "Viola the Magnificent",
  },
});

使用 updateMany 更新多条记录:

const updateUsers = await prisma.user.updateMany({
  where: {
    email: {
      contains: "prisma.io",
    },
  },
  data: {
    role: "ADMIN",
  },
});

使用 delete 删除记录:

const deleteUser = await prisma.user.delete({
  where: {
    email: "bert@prisma.io",
  },
});

使用 deleteMany 删除多条记录:

const deleteUsers = await prisma.user.deleteMany({
  where: {
    email: {
      contains: "prisma.io",
    },
  },
});

使用 include 表示关联查询是否生效,比如:

const getUser = await prisma.user.findUnique({
  where: {
    id: 19,
  },
  include: {
    posts: true,
  },
});

这样就会在查询 user 表时,顺带查询所有关联的 post 表。关联查询也支持嵌套:

const user = await prisma.user.findMany({
  include: {
    posts: {
      include: {
        categories: true,
      },
    },
  },
});

筛选条件支持 equalsnotinnotInltltegtgtecontainssearchmodestartsWithendsWithANDORNOT,一般用法如下:

const result = await prisma.user.findMany({
  where: {
    name: {
      equals: "Eleanor",
    },
  },
});

这个语句代替 sql 的 where name="Eleanor",即通过对象嵌套的方式表达语义。

Prisma 也可以直接写原生 SQL:

const email = "emelie@prisma.io";
const result = await prisma.$queryRaw(
  Prisma.sql`SELECT * FROM User WHERE email = ${email}`
);

参考资料