【セットアップ編】NestJSとPrisma
Prismaの公式チュートリアルに沿って、Prismaのセットアップを行う。
そのほかに参考にした記事→Zenn - Prismaを使った効率的なバックエンド開発ワークフロー
前提条件
- Node.js がインストールされている
- Docker または PostgreSQL がインストールされている
- プロジェクトを作成済みである(
nest new <プロジェクト名>
を実行済みである)
最初のディレクトリ構成
プロジェクト名
├── node_modules
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── README.md
├── nest-cli.json
├── (使用しているパッケージマネージャのlockファイル)
├── package.json
├── tsconfig.build.json
└── tsconfig.json
PostgreSQLのインスタンスを作成する
プロジェクト直下にdocker-compose.yml
を作成する。
# docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:13.5
restart: always
environment:
- POSTGRES_USER=myuser
- POSTGRES_PASSWORD=mypassword
- POSTGRES_DB=mydb
volumes:
- postgres:/var/lib/postgresql/data
ports:
- '5432:5432'
volumes:
postgres:
続いて、
$ docker-compose up -d
を実行し、バックグラウンドでコンテナを起動。
Prismaのセットアップ
次のコマンドでPrismaをインストール。
$ yarn add -D prisma
Prismaの初期化
$ npx prisma init
を実行する。初期化完了後、プロジェクト直下にprisma
ディレクトリとその中にschema.prisma
ファイルが作成され、同時に.env
も作成される。
プロジェクト名
├── node_modules
├── prisma
│ ├──schema.prisma ←ここ
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── .env ←ここ
├── README.md
├── nest-cli.json
├── (使用しているパッケージマネージャのlockファイル)
├── package.json
├── tsconfig.build.json
└── tsconfig.json
Prismaスキーマの定義
Prismaの初期化によって作成されたschema.prisma
は、スキーマとPrismaクライアントの連携やDB接続設定、モデル定義を記述するためのファイル。初期状態ではデフォルトスキーマとしてgenerator
とdatasource
の2つが作成される。
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generatorとdatasourceの概要は次の通り。
generator
: Prisma Client を生成することを示す。Prisma Clientはデータベースにクエリを送信するために使用される。
datasource
: データベース接続の設定パート。上記の構成は、DBとしてPostgreSQL、データベース接続URLとしてDATABASE_URLという環境変数を使用することを示す。
環境変数の設定
.env
ファイルにDATABASE_URLを設定する。最初にdockerで作成したPostgreSQLのインスタンスを設定する。
DATABASE_URL="postgres://myuser:mypassword@localhost:5432/mydb?schema=public"
データモデルの定義
schema.prismaに、UserモデルとArticleモデルを追加する。ここで定義するモデルはDBのテーブルと対応する。
// prisma/schema.prisma
略
model User {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String @unique
hashedPassword String
articles Article[]
}
model Article {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
description String?
userId Int
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
デコレータについて
@id
:モデルの主キーとして設定する。
@default(autoincrement())
:idを自動採番させるよう設定する。
@unique
:ユニーク制約を指定する。
@relation
:リレーションシップを定義する。
リレーションシップの定義
上記のUserモデルとArticleモデルのリレーションは、
User
モデルのarticle
フィールドはArticle
モデルの配列を持っている。Article
モデルのuser
フィールドはUser
モデルを参照している。@Relation()
デコレータにより、Article
モデルのuserId
フィールドとUser
モデルのid
フィールドを紐づけている。また、onDelete: Cascade
によって、Userが削除された場合はそのUserに紐づくArticleも削除されるように指定している。
DBマイグレーション
Prismaのスキーマ定義が完了したら、次のコマンドでテーブル作成を実行する。なお、--nameオプションをつけずに実行した場合は、Enter a name for the new migration?
と聞かれて名前を入力するプロンプトが表示される。
$ npx prisma migrate dev --name "v1"
このコマンドは次の3つの事を行う。
- マイグレーションの保存:
スキーマのスナップショットを作成し、マイグレーションの実行に必要なSQLコマンドを組み立てる。マイグレーションの初回実行時は、新たにPrisma/migrationsフォルダを作成し、そのフォルダ中にスナップショットのフォルダとSQLファイルを保存する。
プロジェクト名
├── node_modules
├── prisma
│ ├──migrations/
│ │ └──202304080823816_v1/
│ │ └──migration.sql
│ └──schema.prisma
略
- マイグレーションを実行:
マイグレーションファイルのSQLを実行してテーブルを作成する。 - Prisma クライアントの生成:
最新のスキーマに基づいてPrismaクライアントを生成する。時点でPrismaクライアントライブラリがインストールされていない場合は、自動でインストールする。→ package.jsonファイルの"dependencies"
に@prisma/client
パッケージが追加される。
"dependencies": {
"@prisma/client": "4.12.0",
},
以下が、マイグレーションによって作成されたSQLファイル
-- prisma/migrations/202304080823816_v1/migration.sql
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"email" TEXT NOT NULL,
"hashedPassword" TEXT NOT NULL,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Article" (
"id" SERIAL NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"title" TEXT NOT NULL,
"description" TEXT,
"userId" INTEGER NOT NULL,
CONSTRAINT "Article_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-- AddForeignKey
ALTER TABLE "Article" ADD CONSTRAINT "Article_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
(マイグレーションの実行毎にスナップショットのフォルダが作成されるが、そのフォルダ名はprisma/migrations/[タイムスタンプ]_[コマンドで指定した名前]/migration.sql
となる)
データの確認
$ npx prisma studio
を実行すると、ブラウザが自動でhttp://localhost:5555/
へアクセスし、schema.prisma
ファイルで定義したモデル構造に基づいたテーブルが作成されていることが確認できる。
おまけ
$npx prisma generate
を実行すると、スキーマのモデル構造を解析してTypeScriptで使用できるUser
とArticle
のデータ型を自動生成してくれる。
以上でセットアップは完了。