6.3-prisma
Create by fall on 25 Sep 2023
Recently revised in 23 Jun 2025
Prisma
prisma 官方是下一代 ORM,不知道是不是可以这样说,但是 Prisma 支持主流的数据库(Postgresql、Mongodb、mysql)并且有项目组长期维护,所以也值得信任。
安装和初始化
首先,在项目中安装 prisma
,npm i prisma
使用 npx prisma version
查看版本信息
prisma 命令用于初始化和创建文件,@prisma/client
用于创建连接和数据库映射。
然后使用命令 npx prisma init
,
初始化为我们提供了两个新的文件 prisma.prisma
和 .env
。
一般来讲,要保证 prisma 和
@prisma/client
的版本统一,来确保行为一致,所以,全局安装 prisma 时要特别注意
连接 mongo
在 prisma.prisma
中写入如下内容
你的架构和数据库之间的“耦合”故意设计得比 SQL 数据库更不严格;MongoDB 不会强制执行该架构,因此你必须验证数据完整性。
为了避免由于数据和架构之间不一致而导致迁移失败,解决方案之一是任何新字段都明确定义为可选。
// datasource 表示你的 prisma 如何连接到数据库
datasource db {
provider = "mongodb"
url = env("DATABASE_URL") // 使用 env 中的 DATABASE_URL 变量
}
// generator 决定了当你运行 prisma generate 命令时,在哪里创建文件
generator client {
provider = "prisma-client-js"
// output = "./generated/prisma-client-js" // 可选,自定义输出的位置
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
slug String @unique
title String
body String
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
comments Comment[]
}
首先使用命令
mongosh
进入 mongodb 的命令行界面,会提供以下内容
Current Mongosh Log ID: 6526a8a80aed2e92c3cd7fa9
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.10.0
Using MongoDB: 5.0.18
Using Mongosh: 1.10.0
prisma 会用到 Connecting to
后面的内容,该链接可以拆解为下面的形式
mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE
# USERNAME: The name of your database user
# PASSWORD: The password for your database user
# HOST: The host where a instance is running
# PORT: The port where your database server is running (typically `27017` for MongoDB)
# DATABASE: The name of the database
我们先使用命令 use myBase
创建数据库 myBase
,然后将下面的内容放到 .env
文件中
# .env 文件中添加以下内容
# 把路径 myBase 添加到上方 Connecting to 的内容中,组合成下面这样
DATABASE_URL="mongodb://localhost:6200/myBase?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.10.0"
最后,在 mongosh 命令行中使用 rs.initiate()
命令初始化 Replica Set
rs.initiate()
# {
# info2: 'no configuration specified. Using a default configuration for the set',
# me: '74b3cecd77b6:27017',
# ok: 1
# }
至此,连接的准备工作已经完成
连接 postgres
// schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("postgresql://userName:password123@localhost:5432/mydatabase?schema=public&connect_timeout=300)
}
安装 client
npm i @prisma/client
安装过程中,也同时运行了 prisma generate
命令,生成用于 prisma 操作的类型文件。
将 prisma 命令放置到 package.json
的 script 中
"scripts": {
// ... 其它脚本
"prisma": "prisma"
}
以后,每当更改 prisma 文件的时候,都要运行 prisma generate
。用来生成 node_modules/@prisma/client
库中的 Typescript 类型,之后就可以获得对应的类型提示。
对于不同类型的数据库,要使用不同的命令来向数据库提交数据格式
# 将当前数据格式提交到数据库
# 将数据模型(data model)同步到数据库中,mongo
pnpm prisma db push
# 创建索引,并且重新生成 @prisma/clinent create new indexes and regenerate Prisma Client.
# 一般关系型数据库
pnpm prisma migrate dev
配置文件
// prisma.config.ts
import path from 'node:path'
import type { PrismaConfig } from 'prisma'
export default {
earlyAccess: true,
schema: path.join('prisma'),
} satisfies PrismaConfig<Env>
使用
添加
-
创建
-
创建新的
Post
record 并且将他连接到User
record
const post = await prisma.post.create({
data: {
title: 'Join us for Prisma Day 2020',
slug: 'prisma-day-2020',
body: 'A conference on modern application development and databases.',
user: {
connect: { email: 'hello@prisma.com' },
},
}
})
同时创建 User 以及 Post
在同一查询中创建新的 User 和新的 Post 记录
const user = await prisma.user.create({
data: {
name: 'Alice',
email: 'alice@prisma.io',
posts: {
create: { title: 'Join us for Prisma Day 2020' },
},
},
})
修改
// Run inside `async` function
const post = await prisma.post.update({
where: { id: 42 },
data: { published: true },
})
删除
app.delete(`/post/:id`, async (req, res) => {
const { id } = req.params
const post = await prisma.post.delete({
where: {
id: Number(id),
},
})
res.json(post)
})
查找
查询 Post
中所有包含 "hello"
的 records
const filteredPosts = await prisma.post.findMany({
where: {
// 过滤所有 title 和 body 包含 hello 的记录
OR: [{ title: { contains: 'hello' } }, { body: { contains: 'hello' } }],
},
})
// 返回每个 user 上包含 posts 的关系
const allUsers = await prisma.user.findMany({
include: { posts: true },
})
使用 fluent relations API to retrieve the Post
records of a User
by traversing the relations
const user = await prisma.comment
.findUnique({
where: { id: '60ff4e9500acc65700ebf470' },
})
.post()
.user()
删除一个 User
record
const deletedUser = await prisma.user.delete({
where: { email: 'sarah@prisma.io' },
})
对比其它技术
原始 SQL
对比 pg,mysql,这些工具可以实现完全控制数据库操作,但生产率低,查询结果没有类型安全
SQL 查询构建器
应用开发者仍然需要根据 SQL 来考虑他们的数据。
传统的 ORM
开发者将应用模型定义为类来抽象化 SQL,这些类映射到数据库中的表。
但实际上 ORM 会生成 SQL JOIN,这些 SQL JOIN 成本高昂,并且有可能大大减慢你的应用速度
数据建模
process of defining the shape and structure of the objects in an application
定义应用中对象的形状和结构的过程
在对数据建模时,你通常会问以下问题:
- 我的应用中的主要实体/概念是什么?
- 他们之间的关系如何?
- 它们的主要特性/特性是什么?
- 他们如何用我的技术堆栈来表示?
参考文章
作者 | 链接 |
---|---|
prisma 官方文档 | Connect your database (MongoDB) |
prisma 对比 mongoose | https://www.prisma.io/docs/orm/more/comparisons/prisma-and-mongoose |