iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
0
Modern Web

React + GraphQL 全端練習筆記系列 第 25

仿Trello - Prisma Migrate 與添加Seeder

本系列文以製作專案為主軸,紀錄小弟學習React以及GrahQL的過程。主要是記下重點步驟以及我覺得需要記憶的部分,有覺得不明確的地方還請留言多多指教。

已經按Prisma schema生成Prisma Client了,不過資料庫連個影都沒有,有Client的CRUD方法也沒用。

接著就來在專案目錄下建立sqlite 資料庫檔案,並且利用Prisma Migrate工具生成資料庫中的Table。

建立Sqlite資料庫

首先在prisma資料夾底下建立 dev.db檔案,這個檔案的位置要符合schema中的datasource url。

//schema.prisma
datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

建立Prisma Migration檔案

要根據Prisma schema生成migration檔案,先多看一眼目前的schema models:

//schema.prisma
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
}

預計要生成 List、Todo兩個Table。

產生migration的方法很簡單,執行指令:

npx prisma migrate save --name init --experimental

就會自動生成migration檔案,可以在prisma/migrations資料夾底下找到生成的檔案。

解釋一下指令的參數:

  • name : migration的命名
  • experimental : 其實撰文時點prisma migrate功能還處於試驗階段,有些功能還不齊,像是重命名現有table等,所以這類試驗功能都要帶上這個指令才能執行。

變更資料庫Model

確認migration成功生成後,就應用到資料庫中:

prisma migrate up --experimental

跑成功後就表示資料庫中已經存在對應Schema的Table。

Prisma Studio

要怎麼確認migration是否成功呢? 可以利用Prisma提供的資料庫檢視與編輯工具,Prisma Studio,這也已經包含在一開始安裝的Prisma套件中了。

執行Prisma Studio:

npx prisma studio

編譯成功後就會自動在瀏覽器上開啟,可以選擇要檢視的Table:

可以看到按照schema的欄位顯示出來,不過有些欄位只是關聯參照而已,不是資料庫實際的欄位,畢竟像list欄位不可能真把整個物件存進去。

想看實際上資料庫有哪些欄位的話,我是用VS Code的SQLite套件,可以直接在VS Code裡顯示table跟執行SQL指令。

可以看到有個_Migration table,這是執行migration時Prisma偷偷建立的,用來記錄每次migration的結果,不管成功或失敗。

新增欄位

若想要新增Model欄位該怎麼操作呢?

跟建立Model時一樣,先編輯Schema:

//schema.prisma
model List {
  id    Int     @default(autoincrement()) @id
  title  String?
  order  Int  @default(0)   //新增order欄位
  todos  Todo[]
}

model Todo {
  id        Int     @default(autoincrement()) @id
  name     String
  order  Int @default(0)   //新增order欄位
  list    List?   @relation(fields: [listId], references: [id])
  listId  Int?
}

接著建立新的migration然後up:

npx prisma migrate save --name add-order --experimental
npx prisma migrate up --experimental

每當schema更新時client也要記得更新:

npx prisma generate

重開studio就能看到table更新了:

Prisma會解析Schema的差異並生成對應的migration,不用在自己編寫對應的migration指令,只要顧好Schema就好,是不是很方便?

undo migration

想要回到之前的migration階段怎麼辦?

目前官方文件中還沒有相應的功能介紹,不過討論串裡有提到可以試試

npx prisma migrate down --experimental 1

會回到上一個Migration的階段。

待未來更新時會實際介紹這個功能吧。

建立Seeder

資料庫裡有對應的Table了,該來實際用用Prisma Client,進行資料庫的存取了。

/*
prisma/seeder/seeder.js
*/
const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();

//dummy data
const lists = [
  {
    title: "list1",
    todos: [
      { name: "todo1", order: 0 },
      { name: "todo2", order: 1 },
    ],
    order: 0,
  },
  {
    title: "list2",
    todos: [
      { name: "todo3", order: 0 },
      { name: "todo4", order: 1 },
      { name: "todo5", order: 2 },
    ],
    order: 1,
  },
];

async function main() {
  await prisma.list.deleteMany();
  await prisma.todo.deleteMany();

  for (let i = 0; i < lists.length; i++) {
    await prisma.list.create({
      data: {
        title: lists[i].title,
        todos: {
          create: lists[i].todos,
        },
        order: lists[i].order,
      },
    });
  }
}

main()
  .catch((e) => {
    throw e;
  })
  .finally(async () => {
    await prisma.$disconnect();
  });

Prisma Client的使用方式大致上就是:

[prisma client 實例].[目標Table].[CRUD方法]

seeder的步驟:

  1. 建立Prisma client 實例
const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();
  1. 建立要寫入資料庫的資料,也就是dummy data的部分。
    可以注意一下,todo物件中都沒有list跟listId資訊。
  2. main函式:
    1. 用 deleteMany() 將List跟Todo table通通清空
    2. 用lists裡的資料create檔案,可以注意這個部分:
todos: {
  create: lists[i].todos,
},

因為todos欄位對應的Todo model,所以可以呼叫create,同時生成Todo資料,並且Prisma會自動按照relation生成外鍵參照,像是這裡會根據建立時的list id,生成 Todo model裡的listId。

  1. 執行main並在成功後中斷通訊: prisma.$disconnect()。

順手到package.json中加入seeder的script,方便操作

"seed": "node ./prisma/seeder/seeder.js"

執行:

npm run seed

到Prisma Studio看看結果:

上圖是連續執行兩次seed後的結果,因為每次都會清空表單再添加資料,只有id會繼續累加,所以目前的List有id=3,4兩筆資料,而Todo中的listId也會同步對應List的id資訊。

這個特性被稱作 Nested writes,可以根據Model的關聯在一個指令中同時在複數Table裡新增資料,並自動建立外鍵參照,很方便。

這邊先以seeder試手,嚐嚐Prisma Client的功能,接下來要回到Apollo Server中串接Prisma Client,利用Prisma Client的方法對接資料庫,並重現Trello Clone的功能。

References:


上一篇
仿Trello - Prisma 安裝與 Schema 建立
下一篇
仿Trello - Apollo Server 串接 Prisma
系列文
React + GraphQL 全端練習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言