iT邦幫忙

2024 iThome 鐵人賽

DAY 9
2
Modern Web

一些讓你看來很強的 ORM - prisma系列 第 9 篇

Day09. 一些讓你看來很強的 ORM - prisma (model)

  • 分享至 

  • xImage
  •  

在 prisma 中我們非常仰賴 schema 去定義我們的 model ,那今天我們就來好好認識一下他~

Models

prisma 得 models 有以下的功能:

  • 關聯資料表到 PostgreSQL,或是對應的 collections (MongoDB)到你的 DB
  • 是 prisma client 的基礎架構。
  • 提供 typescript type definitions 的來源,確保整個 application 的 type safe。

那今天會以下方的 schema 當作本次的範例

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

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

model User {
  id      Int      @id @default(autoincrement())
  email   String   @unique
  name    String?
  role    Role     @default(USER)
  posts   Post[]
  profile Profile?
}

model Profile {
  id     Int    @id @default(autoincrement())
  bio    String
  user   User   @relation(fields: [userId], references: [id])
  userId Int    @unique
}

model Post {
  id         Int        @id @default(autoincrement())
  createdAt  DateTime   @default(now())
  updatedAt  DateTime   @updatedAt
  title      String
  published  Boolean    @default(false)
  author     User       @relation(fields: [authorId], references: [id])
  authorId   Int
  categories Category[]
}

model Category {
  id    Int    @id @default(autoincrement())
  name  String
  posts Post[]
}

enum Role {
  USER
  ADMIN
}

之後我們跑 migration 同步到我們的 DB

>npx prisma migrate dev 

這邊有一個有趣的內容是,每當我們 migration 時候 prisma 會告訴我們是否需要 clean data 好讓 prisma 可以 migration ,這邊會確保 shcmea 的ㄧ至性是否與 data 符合,但你可能會想失去的資料怎麼辦,這邊筆者會在之後得內容分享給大家~

 We need to reset the "test" schema at "sfo1.clusters.zeabur.com:31437"
Do you want to continue? All data will be lost. › (y/N)

打好 migration 名稱後就完成了~

✔ Enter a name for the new migration: … test
Applying migration `20240918153431_test`

The following migration(s) have been created and applied from new schema changes:

migrations/
  └─ 20240918153431_test/
    └─ migration.sql

Your database is now in sync with your schema.

✔ Generated Prisma Client (v5.19.1) to ./node_modules/@prisma/client in 93ms

Model Name

prisma 有針對 schema 的 model name 有一套 Naming conventions 如下:

正則表達式:

模型名稱必須符合 [A-Za-z][A-Za-z0-9_]* 的正則表達式。
這意味著模型名稱必須以字母開頭,後面可以接任意數量的字母、數字或下劃線。

命名風格:

模型名稱應該使用帕斯卡命名法(PascalCase)。
例如:User、Product、Order 等。

數詞形式:

模型名稱應該使用單數形式。
不要使用複數形式,如 users 或 products。
也不要使用大寫形式,如 USERS。

禁用詞:

Prisma 有許多內部使用的保留字不能作為模型名稱。
保留字

來源

但當然如果你不想遵守 prisma 的 Naming conventions 的話,prisma 有提供一個 attribute @@map 讓你直接自動 mapping 到 DB 的 table

model Comment {
  // Fields

  @@map("comments")
}

Defining fields

在 prisma 中有一些 attribute 去對應 scalar filed 大家可以在使用時查表看看~ 完整的 scalar field types

例如 String 可以對應到 text、 varchar、TEXT 等等的 scalar type 根據不同的 DB 。

Connector Default mapping
PostgreSQL text
SQL Server nvarchar(1000)
MySQL varchar(191)
MongoDB String
SQLite TEXT
CockroachDB STRING
model Comment {
  id      Int    @id @default(autoincrement())
  title   String
  content String
}

或者你要用直接使用原生的 scalar types 也是 OK

model Post {
  id      Int    @id
  title   String @db.VarChar(200)
  content String
}

Relation fields

如果要表達關聯關係可以透過 [] 並在對應的 table 用 @relation 描述關聯的對應欄位。

以及 ? 代表著這個欄位是 optional

model Post {
  id       Int       @id @default(autoincrement())
  // Other fields
  comments Comment[] // A post can have many comments
}

model Comment {
  id     Int
  // Other fields
  post   Post? @relation(fields: [postId], references: [id]) // A comment can have one post
  postId Int?
}

如果是多對多則使用 [] 就可以

model Post {
  id       Int       @id @default(autoincrement())
  // Other fields
  comments Comment[] // A list of comments
  keywords String[] // A scalar list
}

Defining attributes

有時候我們需要描述 fileds 中他是 table 的 id 欄位,或是有沒有 default value 等等,這些我們都需要額外定一下 attributes

Defining an ID field

ID 對 table 來說一個 unique 的欄位,對應著不同的 record ,用法如下

model User {
  id      Int      @id @default(autoincrement())
  name    String?
}

補充一下如果再 relational databases 中如果你的 schema 沒有定 id 要記得提供一個 @unique 的 fields

@id 除了訂在單一一個欄位,也可以結合多個欄位的組合當作 id

model User {
  firstName String
  lastName  String
  email     String  @unique
  isAdmin   Boolean @default(false)

  @@id([firstName, lastName])
}

預設情況下的個 model 的 id 將會叫做 firstName_lastName ,如果想要客製化 id name ,可以直接改在 @@id 中。

model User {
  firstName String
  lastName  String
  email     String  @unique
  isAdmin   Boolean @default(false)

  @@id(name: "fullName", fields: [firstName, lastName])
}

Defining a default value

同樣的你也可以指定某一個 fields 的 default value 是什麼,例如指定 createdAt 時間,或者是 published 這種 boolean 欄位等等

model Post {
  id         Int        @id @default(autoincrement())
  createdAt  DateTime   @default(now())
  title      String
  published  Boolean    @default(false)
  data       Json       @default("{ \"hello\": \"world\" }")
  author     User       @relation(fields: [authorId], references: [id])
  authorId   Int
  categories Category[] @relation(references: [id])
}

補充一個在 prisma 中 default 可以接受以下的值。

  • Static values :例如 string 、boolean、int 等等
  • Lists:代表陣列資料如 [5, 6, 8] (Int[]) or ["Hello", "Goodbye"] (String[])。
  • Functions:now() 指定當前時間,uuid() 自動產生 id 等等。
  • JSON data:這邊記得使用 double-quotes 去塞你的 json data ,@default("[]") ,或是你想使用 json object 記得加上反斜線 @default("{ \"hello\": \"world\" }").

Enum Type

和 ts 一樣我們可以定義 enum 當作 fileds 的 type

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  role  Role    @default(USER)
}

enum Role {
  USER
  ADMIN
}

大家如果有問題可以來小弟的群組討論~

✅ 前端社群 :
https://lihi3.cc/kBe0Y


上一篇
Day08. 一些讓你看來很強的 ORM - prisma (schema)下
下一篇
Day10. 一些讓你看來很強的 ORM - prisma (relation)介紹
系列文
一些讓你看來很強的 ORM - prisma 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言