iT邦幫忙

2024 iThome 鐵人賽

DAY 9
2
Modern Web

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

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

  • 分享至 

  • xImage
  •  

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

Models

prismamodels 有以下的功能:

  • 關聯資料表到 PostgreSQL,或是對應的 collections (MongoDB)到你的 DB
  • prisma client 的基礎架構。
  • 提供 typescript type definitions 的來源,確保整個 applicationtype 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 有針對 schemamodel name 有一套 Naming conventions 如下:

正則表達式:

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

命名風格:

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

數詞形式:

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

禁用詞:

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

來源

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

model Comment {
  // Fields

  @@map("comments")
}

Defining fields

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

例如 String 可以對應到 textvarcharTEXT 等等的 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 中他是 tableid 欄位,或是有沒有 default value 等等,這些我們都需要額外定一下 attributes

Defining an ID field

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

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

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

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

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

  @@id([firstName, lastName])
}

預設情況下的個 modelid 將會叫做 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

同樣的你也可以指定某一個 fieldsdefault 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])
}

補充一個在 prismadefault 可以接受以下的值。

  • Static values :例如 stringbooleanint 等等
  • 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 當作 filedstype

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 - prisma30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言