Prisma大好き!
おはようございます!こんにちは!こんばんは!はじめまして!
スターフェスティバルの DPontaro です!
この記事は スターフェスティバル Advent Calendar 2022 の5日目の記事です!!!!!
昨日はあひるさん の terraform のお話でした。
私もterraformはまだまだ慣れておらずで、こうした実例はめっちゃ参考になりますね!
さてさて本日はインフラからは離れてPrismaというORMについて紹介します!!!!!
Prismaとは
Node.js、TypeScript用のORMです。
仲良くなるまで多少の苦労は伴いますが、それに見合うメリットがあります!
migration と Prisma Client
まずは Prisma schemaを定義します。
このschemaファイルは、DBテーブルの定義とPrisma Clientが生成するmodelの定義を行うことができます。
簡単に3テーブルほど定義してみます。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
id String @id
name String
mailAddress String @map("mail_address")
cart Cart[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
@@map("user")
}
model Products {
id String @id
name String
description String
price Int
cart Cart[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
@@map("products")
}
model Cart {
id String @id
user User @relation(fields: [userId], references: [id])
userId String @map("user_id")
product Products @relation(fields: [productId], references: [id])
productId String @map("product_id")
createdAt DateTime @default(now()) @map("created_at")
@@map("cart")
}
model間の関係性は @relation で定義します。
これはテーブルの外部キー制約になるのと
クエリでデータを取得する際に重要な要素となります。
他の細かいルールは公式ドキュメントを確認ください。
prisma migrateコマンドを実行すると
- migration用のsqlファイル生成
- migrationの実行
- Prisma Clientの生成
が行われます。
$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "dev.db" at "file:./dev.db"
SQLite database dev.db created at file:./dev.db
Applying migration `20221201143200_init`
The following migration(s) have been created and applied from new schema changes:
migrations/
└─ 20221201143200_init/
└─ migration.sql
Your database is now in sync with your schema.
✔ Generated Prisma Client (4.7.0 | library) to ./node_modules/@prisma/client in 33ms
生成されたsqlがこちら
-- CreateTable
CREATE TABLE "user" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"mail_address" TEXT NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateTable
CREATE TABLE "products" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"description" TEXT NOT NULL,
"price" INTEGER NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateTable
CREATE TABLE "cart" (
"id" TEXT NOT NULL PRIMARY KEY,
"user_id" TEXT NOT NULL,
"product_id" TEXT NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "cart_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "cart_product_id_fkey" FOREIGN KEY ("product_id") REFERENCES "products" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
Prisma Clientに生成された一部モデルが下記になります。
/**
* Model User
*
*/
export type User = {
id: string
name: string
mailAddress: string
createdAt: Date
updatedAt: Date
}
migrationも実行でき、定義したmodelのtypeも生成されTypeScriptの恩恵も存分に受けられます!
クエリがさくさく書ける
findUniqueやfindManyなどでシンプルにデータを取得できます
const user = prisma.user.findUnique({
where: {
id: "test",
},
});
const users = prisma.user.findMany();
またschema定義で@relationを定義したmodelであればincludeを指定してJOINした状態で取得することもできます
const cart = await prisma.cart.findUnique({
where: {
id: "test",
},
include: {
user: true,
product: {
select: {
id: true,
name: true,
}
},
},
});
console.log(cart);
console.logの結果が↓になります。
{
id: 'test',
userId: 'userTestId',
productId: 'productTestId',
createdAt: 2022-12-02T02:05:53.764Z,
user: {
id: 'userTestId',
name: 'DPontaro',
mailAddress: '',
createdAt: 2022-12-02T02:04:22.682Z,
updatedAt: 2022-12-02T02:04:22.682Z
},
product: { id: 'productTestId', name: 'テスト商品' }
}
include中のuserはtrueが指定されているので、全カラムを取得していますが、
productはselectで、idとnameのみを指定しているのでカラムが絞られた状態で取得されているのがわかります。
慣れるのにある程度時間はかかりますが、schemaのrelationをしっかり把握すると、
さくさく必要なデータを取得するクエリを書くことができ、非常に開発体験が良いです。
GUIツール Prisma Studio
標準でGUI管理ツールも搭載されています。
$ npx prisma studio
これでサクッと立ち上がります。
手入力でデータも作れますし
relationがあれば、データを選択してポチポチっと作成することもできます。
関連パッケージあれこれ
prisma-erd-generator
schemaからER図出力することができます。
schemaに下記定義を追加
generator erd {
provider = "prisma-erd-generator"
output = "../ERD.md"
}
prisma generateを実行。
こんな感じに仕上がります。
導入時不具合もあったので、修正のPullRequestも出してそれが取り込まれたりもしました。
OSSコミットは良いことづくめなので、積極的に取り組んでいくことをオススメします!
jest-prisma
Prismaを使用したテストについては、こちらの記事がすごく参考になりました。
特に記事中に出てくるjest-prismaはテストスコープ毎にトランザクションが貼られて
勝手にロールバックされるので、テストデータの後片付けなどが不要となり非常に便利です!
まとめ
ということで慣れるのに苦労もありましたが、
今はガリガリクエリ書けるようになって非常に楽しいです!
まだまだ使い込んでいくつもりなので、他にもこんな使い方あるよ!
とかあれば是非教えてください!
採用とか宣伝とか
プロダクト開発部のtwitterアカウント
Podcast
などなど情報発信しております!
スターフェスティバルまだまだ積極採用中ですので、興味ありましたらカジュアル面談から是非是非!
ご応募お待ちしてます!
ウェルウェルカムカム!!
Discussion