はじめに
こんにちは、株式会社TOKOSのツキヤです!
今回はJavaScriptでサーバーサイドを記述する際に使うPrismaというライブラリについて、特にschema(スキーマ)の記述について解説します!
Prismaの概要
まずは、Prismaについて簡単に説明します!
PrismaはDB(データベース)の操作に必要な実装を1つのライブラリで全てできるような、かなりいい感じのJavaScriptのライブラリです!
具体的には、ざっくり「マイグレーション」「クエリビルダー」「GUIツール」の3つの機能を提供してくれます!
データベースのスキーマ変更を管理するためのツールです!
マイグレーションファイルを使って、データベーススキーマの変更を追跡し、バージョン管理をすることが可能です。
Railsで言うところの、マイグレーションファイル + rails db:migrate
だね!
メインとなる機能で、直感的な記述方法でDBからデータを取得するものです!
(Railsで例えるとActiveRecord
に相当します)
データベースの内容を視覚的に閲覧し、編集できるGUIツールです。
データベースの管理(編集)やデバッグが簡単に可能となります!
スキーマとは?
スキーマについても、少し説明をします!
簡単に言うと、「DBの構造を定義したファイル」です😎
このファイルを見ることで、人間はDBの内容を簡単に把握できるし、プログラミング言語側はDBに実際にデータ構造を設定することができます✨
今回試すテーブル
それでは、今回定義するテーブル群を説明します!
今回は簡単な投稿サービスと定義します!
また、「型」に関してはMySQLという前提で説明します。
カラム名 | 型 | 説明 |
id | bigint | 主キー |
name | varchar | ユーザー名 |
varchar | メールアドレス | |
age | integer, Allow NULL | 年齢 |
カラム名 | 型 | 説明 |
id | bigint | 主キー |
user_id | bigint | usersテーブルに対する外部キー |
title | varchar | 投稿タイトル |
body | text | 投稿本文 |
カラム名 | 型 | 説明 |
id | bigint | 主キー |
name | varchar | タグ名 |
カラム名 | 型 | 説明 |
id | bigint | 主キー |
post_id | bigint | postsテーブルに対する外部キー |
tag_id | bigint | tagsテーブルに対する外部キー |
上記の4つテーブルを定義したスキーマを定義していきます!!
今回は「多対多」等の説明は省きます🙏
schemaの記述
早速、定義ファイルを記述していきます!
まずは、下記コマンドを実行してください。 (必要なライブラリのprisma
、@prisma/client
はインストール済みという前提です🙏)
$ npx prisma init
これで、./prisma/schema.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 = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
age Int?
posts Post[]
@@map("users")
}
model Post {
id Int @id @default(autoincrement())
userId Int @map("user_id")
title String
body String @db.Text
user @relation(fields: [userId], references: [id], onDelete: Cascade)
tags Tag[]
@@index([userId])
@@map("posts")
}
model Tag {
id Int @id @default(autoincrement())
name String
posts Post[]
}
上記の記述をすることで、先程のテーブル群を作成することができます!!
それでは次章から解説します!
解説
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
この部分は、使用するRDBMS等に合わせて書き換えます!
今回自分は「PlanetScale」というサービスを使うので、このような記述にしました!
usersテーブル
model User {
//...
}
このような記述で、各テーブルの宣言を行います!
id Int @id @default(autoincrement())
基本は1つ目にカラム名、2つ目に型、3つ目の塊にその他設定を記載します!
ここでは、「idというカラム名で、Int型で、主キーで(オートインクリメントして)」という意味です!
この記述で、1から始まってオートインクリメントされる主キーのid
カラムを登録できます!
name String
これはシンプルにname
というVARCHAR型のカラムを定義 という意味になります!
email String @unique
こちらは、name
カラムに@unique
というものが追加されています。
@unique
は、そのカラムの値を一意にするという意味になります!
メールアドレスは同じものは使ってほしく無いのでこのような制約が必要ですね👍
age Int?
こちらは、「integer型で、NULLも許可する」という意味です!
NULLを許可するなら ? を追加するだけでOKです😎
posts Post[]
これは、posts
テーブルを多数持つ という意味で、Prisma Clientの使用時にusersとpostsを上手く取得できるようにするための設定です!
@@map("users")
}
このように記述することで、JavaScript側から扱う時はUser
、実DBのテーブル名はusers
にすることができます!
テーブル名は基本的にスネークケースが良いので、@@map
の記述はした方がいいかも!
postsテーブル
ここからはまだ説明していない部分について解説します!
userId Int @map("user_id")
このように記述することで、JavaScript側から扱う時はuserId
、実カラム名はuser_id
とすることができます!
body String @db.Text
@db.Text
と記述することで、VARCHARではなくTEXT型として登録することができます!
(VARCHARは最大文字数が255文字なので、それ以上の文字数を扱いたい場合はこの設定をします)
user @relation(fields: [userId], references: [id], onDelete: Cascade)
@relation
の記述をすることで、他のテーブルに対してのリレーションを設定できます!
fields
: どのカラムを外部キーとするか
references
: 親テーブルのどのカラムを見るか
onDelete
: 親テーブルが削除された時にどのような挙動をさせるか
→ Cascade
の場合、親のレコードが削除された場合は子のレコードも削除される
@@index([userId])
これで、userId
カラムに対してインデックスを設定することができます!
インデックスについてよく分からない人は、一旦外部キーには上記のようにしてインデックスを設定するようにしておこう!
tagsテーブル
tagsテーブルについては、今まで説明したものの組み合わせで記述可能なので、割愛します。
posts_tagsテーブル
最後に、postsテーブルとtagsテーブルを多対多にするための中間テーブルを作成します!
…なのですが、実は中間テーブルはmodel
のような定義をしなくても自動で作成されます!
model Post {
// ....
tags Tag[]
}
model Tag {
// ....
posts Post[]
}
ポイントは上記の設定箇所です!
このように、お互いがお互いを複数持つように設定をすることで、Prisma側が自動で中間テーブルを設定してくれるのです✨
コマンド
schemaファイルの記述が完了したら、
$ npx prisma db push
上記コマンドを打つことでDBへの反映が完了します!
DBのテーブルを確認すると、意図したテーブル群ができているはずです💪
おわりに
今回は、Prismaの中でもschemaに焦点を当てて解説をしました!
この記事だけでは網羅できていないので、詳しくは公式サイトを参考にしてみてください🙏