本系列文以製作專案為主軸,紀錄小弟學習React以及GrahQL的過程。主要是記下重點步驟以及我覺得需要記憶的部分,有覺得不明確的地方還請留言多多指教。
前篇提到簡化的Prisma介面建立步驟大致如下:
這次就來從頭建立Schema開始,簡單串接一個sqlite資料庫。
npm安裝Prisma CLI:
npm install @prisma/cli --save-dev
Prisma Client,Prisma Migration等工具都包含在這了,之後可以用指令呼叫這些功能。
server中建立prisma資料夾,然後建立schema.prisma:
/*
/server/prisma/schema.prisma
*/
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
generator client {
provider = "prisma-client-js"
}
model List {
id Int @default(autoincrement()) @id
title String
todos Todo[]
}
model Todo {
id Int @default(autoincrement()) @id
name String
list List @relation(fields: [listId], references: [id])
listId Int
}
Schema的內容待會介紹,目前看到的文字應該是單色的,因為編譯器認不得.prisma這個檔名,如果用的是VS Code,可以安裝Prisma套件幫助標色與自動完成。
接著依序介紹Prisma Schema的構成。
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
url部分因為這次打算用專案目錄底下的sqlite db,所以用file指定db檔案的路徑。
正式的話就是帶上資料庫的連結
datasource db {
provider = "postgresql"
url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public"
}
或是用env指定連結
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
主要定義當用CLI執行 prisma generate指令時的行為。
可以追加參數:
model List {
id Int @default(autoincrement()) @id
title String
todos Todo[]
}
model Todo {
id Int @default(autoincrement()) @id
name String
list List @relation(fields: [listId], references: [id])
listId Int
}
資料模型,也就是資料庫的參照,跟GraphQL Schema的觀念一樣,一個model type底下有數個field,field也分為 scalar fields 跟 relation fields。
詳細介紹fields前,先介紹兩個特殊標記
todos Todo[]
list List?
回頭介紹欄位種類:
Scalar fields: 純量資料欄位,像是Int,String,Boolean,Float還有 DateTime。
可以在每個field之後加上屬性標籤,舉例一些標籤:
@id :標記欄位為一個model的主鍵,通常會搭配autoincrement自動遞增
@unique :標記該欄位必須為獨特值,像是email
@default : 標記該欄位的預設值,像是
@relation : 定義與其他model的關聯,接著會介紹。
Relation fields: 表示不同Model間關聯的欄位,筆記幾個常用關聯的寫法:
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
}
注意這兩行:
user User @relation(fields: [userId], references: [id])
userId Int
在Profile中建立了外鍵userId的欄位,並在user關聯欄位上用 @relation指明userId對應的是 User model裡的 id欄位,就形成關聯了。
relation中,fields為自己的欄位,關聯到references,也就是目標model的欄位。
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
}
跟單對單時相同,Post建立authorId並指定relation關聯,只是在User側的post欄位對應的是Post陣列。
Trello專案的List跟Todo也是這種關聯方式。
model Post {
id Int @id @default(autoincrement())
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
posts Post[]
}
在兩個model各自宣告資料陣列欄位,就形成多對多關係,單純這樣宣告Prisma就會幫助建立relation table,以雙方model的id關聯。
(圖片來源: Prisma)
然後在生成Prisma Client後可以用connect()宣告資料間的關聯,之後會介紹。
如果想要relation table帶有更多資訊,像是createdAt,也可以自行宣告:
model Post {
id Int @id @default(autoincrement())
title String
categories CategoriesOnPosts[]
}
model Category {
id Int @id @default(autoincrement())
name String
posts CategoriesOnPosts[]
}
//自行宣告relation model
model CategoriesOnPosts {
post Post @relation(fields: [postId], references: [id])
postId Int
category Category @relation(fields: [categoryId], references: [id])
categoryId Int
createdAt DateTime @default(now()) //增加自選欄位
@@id([postId, categoryId])
}
model User {
id Int @default(autoincrement()) @id
name String?
successorId Int?
successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id])
predecessor User? @relation("BlogOwnerHistory")
}
需要新增一個外鍵(successorId)做關聯用,並且relation需要多加一個字串命名這個關聯,並且關聯的欄位要用同一個名稱,畢竟可能同時有多個自相關關係。
Schema寫好後可以到指令視窗輸入
npx prisma generate
接著就會解析Schema並生成Prisma Client,成功編譯的話會在node_modules/@prisma/client (預設路徑) 找到生成的程式。
不過目前沒有資料庫供操作,留待明天用Prisma Migration生成資料庫表單並撰寫seeder吧。