该文档的基础是建立在学过关系型数据库的基础上,并且以下内容是根据 API 文档进行参考编写的(没办法,概念那太零散了)。
https://prisma.yoga/getting-started
常用命令
- 先介绍几个命令
# 1) 现有库
pnpm i prisma --save-dev
pnpm i @prisma/client
# 2) 新库
mkdir hello-prisma
cd hello-prisma
pnpm init -y
pnpm install prisma typescript ts-node @types/node --save-dev
pnpm i @prisma/client
# 创建项目
npx prisma init
# 拉取数据库模型
npx prisma db pull
# 生成你的Prisma Client库
# 作用: 在 pull 模型后生成连接库
npx prisma generate
# 模型映射到数据库架构
# 用法: 修改完数据模型后 映射到 数据库架构
npx prisma migrate dev --name init
tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"outDir": "dist",
"strict": true,
"lib": ["esnext"],
"esModuleInterop": true
}
}
.env
USER
: 数据库用户的名称PASSWORD
: 数据库用户的密码PORT
: 数据库服务器运行的端口(关系型数据库通常是3306
)DATABASE
: 数据库名称
DATABASE_URL="MYSQL://USER:PASSWORD@HOST:PORT/DATABASE"
prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "关系型数据库"
url = env("DATABASE_URL")
}
简单的查询
查询 user 表的所有数据
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();
});
npx ts-node index.ts
数据模型
每个 Model 必须至少定义以下一个属性:
@unique
- ``@@unique`
@id
@@id
字段类型这里不会讲,请自行看文档。
字段修饰符
该内容建议直接看 关系 章节。
?
:可选(零个或一个)Profile?
:一个用户对应 零或一个配置文件。
[]
:零个或多个Post[]
:一个用户可以有多篇文章
model User {
id Int @id @default(autoincrement())
name String?
}
model User {
id Int @id @default(autoincrement())
posts Post[]
favoriteColors String[]
}
MongoDB
- 不同点
- 标量列表需要
@db.Array(String)
,其中参数与标量类型匹配(例如,String[]
)
model User {
id String @id @default(dbgenerated()) @map("_id") @db.ObjectId
posts Post[]
favoriteColors String[] @db.Array(String)
}
属性
关系型数据库
- 1、ID
- 单字段:
@id
- 复合字段:
@@id([])
- MongoDB 不支持
@@id
- 单字段:
- 2、默认值
@default
- 3、唯一值
- 单字段:
@unique
- 复合字段:
@@unique([])
- 单字段:
- 4、索引
@@index([title, content])
- 5、定义关系(请看关系 一对多 章节)
@relation
- 对应数据库类型:
FOREIGN KEY
/REFERENCES
@relation
属性上的name
参数的名称可以省略(references
是必需的)
- 6、映射
@@map()
- 将
Post
模型映射至数据库Posts
表。
- 将
- 7、获取更新时间
@updatedAt
-- 关系型数据库
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String @db.VarChar(255)
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
@@unique([authorId, title])
@@index([title, content])
@@map("Posts")
}
model User {
firstName String
lastName String
email String @unique
posts Post[]
@@id([firstName, lastName])
}
MongoDB
- 只讲和 关系型数据库 的不同点。
- 1、ID
- 使用
String
或者Bytes
字段类型 - 使用
@db.ObjectId
对字段修饰 - (可选),使用
@default()
值对字段进行注释,该值使用dbgenerated()
函数 自动生成ObjectId
- 使用
- 2、索引
- 不支持
-- MondoDB
model Post {
id String @id @default(dbgenerated()) @map("_id") @db.ObjectId
createdAt DateTime @default(now())
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
categories Category[] @relation(references: [id])
}
model User {
id String @id @default(dbgenerated()) @map("_id") @db.ObjectId
id String @db.ObjectId @map("_id") @default(dbgenerated())
}
属性函数
autoincrement()
:自增- 不支持 MondoDB
cuid()
:唯一标识符- 和
String
类型兼容
- 和
uuid()
- 和
String
类型兼容
- 和
now()
:当前时间戳- 和
DateTime
类型兼容。
- 和
-- 关系型数据库
model User {
id String @id @default(autoincrement())
id String @id @default(cuid())
id String @id @default(uuid())
createdAt DateTime @default(now())
}
-- mongoDB
model User {
id String @id @default(cuid()) @map("_id")
id String @id @default(uuid()) @map("_id")
createdAt DateTime @default(now())
}
枚举
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
role Role @default(USER)
}
enum Role {
USER
ADMIN
}
关系
一对一
- 指两侧最多可以关联 一条 记录的关系。
- 例如下面例子
- 一个
User
可以有零或一个Profile
- 但是一个
Profile
必须要关联一个User
- 一个
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` 属性中使用)
}
对应以下 SQL
CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Profile" (
id SERIAL PRIMARY KEY,
"userId" INTEGER NOT NULL UNIQUE,
FOREIGN KEY ("userId") REFERENCES "User"(id)
);
- 同时可以在另一侧存储关系外键
model User {
id Int @id @default(autoincrement())
profile Profile? @relation(fields: [profileId], references: [id])
profileId Int? // 关系标量字段 (在上述 `@relation` 属性中使用)
}
model Profile {
id Int @id @default(autoincrement())
user User?
}
- 多字段关系——仅限关系数据库
model User {
firstName String
lastName String
profile Profile?
@@id([firstName, lastName])
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userFirstName, userLastName], references: [firstName, lastName])
userFirstName String // 关系标量字段 (在上述 `@relation` 属性中使用)
userLastName String // 关系标量字段 (在上述 `@relation` 属性中使用)
}
一对多
- 一个
User
可以有零或多个Post
(注意,这里是多个,上面一对一是 一个) - 但是一个
Post
必须要关联一个User
- 注意!这是
Post[]
- 注意!这是
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
}
- SQL
- 注意,
"authorFirstName" TEXT NOT NULL,
这里相比一对一少了UNIQUE
- 注意,
CREATE TABLE "User" (
firstName TEXT,
lastName TEXT,
PRIMARY KEY ("firstName","lastName")
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"authorFirstName" TEXT NOT NULL,
"authorLastName" TEXT NOT NULL,
FOREIGN KEY ("authorFirstName", "authorLastName") REFERENCES "User"("firstName", "lastName")
);
多对多
- 两个具有多对多关系的模型,例如
Category
和Post
- 一个模型作为关系表,例如底层数据库的
CategoriesOnPosts
(有时也称为 JOIN、链接(link) 或 中间(pivot) 表) - 此例中,关系表模型 定义了额外的字段 来描述
Post
/Category
关系 - 谁指定了此类别 (assignedBy
),以及何时指定 (assignedAt
):
model Post {
id Int @id @default(autoincrement())
title String
categories CategoriesOnPosts[]
}
model Category {
id Int @id @default(autoincrement())
name String
posts CategoriesOnPosts[]
}
model CategoriesOnPosts {
post Post @relation(fields: [postId], references: [id])
postId Int // 关系标量字段 (在上述 `@relation` 属性中使用)
category Category @relation(fields: [categoryId], references: [id])
categoryId Int // 关系标量字段 (在上述 `@relation` 属性中使用)
assignedAt DateTime @default(now())
assignedBy String
@@id([postId, categoryId])
}
对应 SQL
CREATE TABLE "Category" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY
);
-- Relation table + indexes -------------------------------------------------------
CREATE TABLE "CategoryToPost" (
"categoryId" integer NOT NULL,
"postId" integer NOT NULL,
"assignedBy" text NOT NULL
"assignedAt" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY ("categoryId") REFERENCES "Category"(id),
FOREIGN KEY ("postId") REFERENCES "Post"(id)
);
CREATE UNIQUE INDEX "CategoryToPost_category_post_unique" ON "CategoryToPost"("categoryId" int4_ops,"postId" int4_ops);