【Drizzle ORM シリーズ】
・Drizzle ORM を Next.js で使ってみる #Next.js - Qiita
https://qiita.com/sigeta/items/c0a2b0463eca06314906
・Drizzle ORM でスキーマファイルを使ってDBを操作する方法 #Next.js - Qiita
https://qiita.com/sigeta/items/99a625c17c6a0a75da54
・Drizzle ORM でリレーションを張る方法 #Next.js - Qiita
https://qiita.com/sigeta/items/b800f3e38beb1639d2b7
・Drizzle ORM の設定ファイルを接続時も利用する方法 #TypeScript - Qiita
https://qiita.com/sigeta/items/d9267a06061d4d2a51e8
・Drizzle ORM でダミーデータを流し込む方法 #TypeScript - Qiita
https://qiita.com/sigeta/items/8bc85b74273eeb37c27a
はじめに
Drizzle ORM
には、DBを操作する CLI kit が付属している。
これを使って、スキーマ作成、マイグレーション、データの取得をやってみる。
まず初めに drizzle-kit
をインストールしておこう。
$ npm i drizzle-kit
設定ファイル
Drizzle ORM
を利用する際の設定を drizzle.config.ts
に記載する。
import { defineConfig } from 'drizzle-kit'
import process from 'node:process'
process.loadEnvFile()
export default defineConfig({
dialect: 'sqlite',
schema: './db/schema.ts',
out: './db/drizzle',
casing: 'snake_case',
dbCredentials: {
url: process.env.DATABASE_URL!,
},
})
-
dialect
: 利用するDBの種類を指定する -
schema
: スキーマファイルを配置する場所を指定する- ここにテーブル定義を記載する
-
out
:drizzle
のDB管理ファイルを配置する場所を指定する- このフォルダは編集禁止
-
casing
:snake_case
を指定すると、列名を自動的にスネークケースに変換してくれる -
dbCredentials
: DB接続情報- SQLite の場合は
url
にファイル名を記載する
- SQLite の場合は
dbCredentials
の情報は .env
ファイルに記載するとよい。
process.loadEnvFile()
を使うことで .env
の内容を読み取れる。
DATABASE_URL='test.sqlite'
Drizzle ORM の初期化
Drizzle ORM
は以下の画像のような構成になっている。
schema.ts
にてテーブルを定義し、DBの状態は drizzle
フォルダに吐き出して、ファイル管理する。
drizzle
はいわば package-lock.json
のようなもの。
なので、いったん pull
を行って現時点の空のDBの状態を吐き出す。
$ npx drizzle-kit pull
[✓] 0 tables fetched
[✓] 0 columns fetched
[✓] 0 indexes fetched
[✓] 0 foreign keys fetched
[⣷] 0 policies fetching
[✓] 0 check constraints fetched
[✓] 0 views fetched
[✓] Your SQL migration file ➜ db/drizzle/0000_icy_adam_warlock.sql 🚀
[✓] You schema file is ready ➜ db/drizzle/schema.ts 🚀
[✓] You relations file is ready ➜ db/drizzle/relations.ts 🚀
結果以下のファイルが出力された。
スナップショットやマイグレーションのSQLファイルが生成される。
これらは管理ファイルのため、直接の操作はやめよう。
スキーマファイルからマイグレーションを生成する
一番簡単な方法として、スキーマファイルからマイグレーションを実施する。
今回は簡単なユーザーテーブルを用意する。
import { sql } from 'drizzle-orm'
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
export const users = sqliteTable('users', {
id: integer().notNull().primaryKey(),
name: text().notNull(),
age: integer(),
created_at: integer({ mode: 'timestamp' }).notNull()
.default(sql`(unixepoch())`),
updated_at: integer({ mode: 'timestamp' }).notNull()
.default(sql`(unixepoch())`)
.$onUpdate(() => sql`(unixepoch())`),
})
export type User = typeof users.$inferSelect
用意したら generate
コマンドを実行して、migration
ファイルを生成する。
$ npx drizzle-kit generate
1 tables
users 5 columns 0 indexes 0 fks
[✓] Your SQL migration file ➜ db/drizzle/0001_daily_black_widow.sql 🚀
結果以下のファイルが出力された。
新しく 0001
に今回の差分(空 -> usersテーブル作成)が作成された。
中身を見てみると今回の変更用のSQLクエリや構造が記録されている。
ファイル名はランダムみたい。
最後に push
コマンドにて、DBへ反映する。
$ npx drizzle-kit push
DBを確認する
Drizzle ORM
には studio
という、DBのビューワーが付属している。
こちらを実行してDBの状況を確認したり、SQLを実行したりすることが可能。
$ npx drizzle-kit studio
=> https://local.drizzle.studio/
試しに一行追加してみる。
編集もお手軽で文句なし!
Next.js
より利用する
最後に今回作成したデータを、Next.js
より利用する。
設定ファイルを仕込んだ、DB接続用のファイルを作成する。
こちらを drizzle()
の代わりに呼び出す。
import { drizzle, type BetterSQLite3Database } from 'drizzle-orm/better-sqlite3'
import Database from 'better-sqlite3'
import * as schema from './schema'
import process from 'node:process'
process.loadEnvFile()
const sqlite = new Database(process.env.DATABASE_URL!)
export const db: BetterSQLite3Database<typeof schema> = drizzle(sqlite, {
schema,
casing: 'snake_case',
})
こちらでも casing: 'snake_case'
を付与する必要がある。
次に、リポジトリにユーザーを全件取得するコードを書く。
書き味は SQL そっくり。
'use server'
import { db } from '@/db'
import { users } from '@/db/schema'
import { asc } from 'drizzle-orm'
import { drizzle } from 'drizzle-orm/better-sqlite3'
export const getUsers = async () => {
const result = await db
.select()
.from(users)
.orderBy(asc(users.id))
return result
}
ページを読み込んだ際に console.log
に出力する。
import { getUsers } from '@/lib/repository'
useEffect(() => {
getUsers().then(res => console.log(res))
}, [])
取れたぁ。
Date
型への変換も勝手にやってくれるみたい。