Drizzle ORMでのスキーマ宣言の概要

Drizzle ORMでは、TypeScriptでデータベーススキーマを直接定義でき、テーブルやカラム、制約などの各モデルをコードベースで管理することができます。スキーマはDrizzle ORMとDrizzle Kitを通じてデータベースの「真実の源(source of truth)」として機能し、クエリとマイグレーションの生成に活用されます。このブログでは、単一ファイルや複数ファイルによるスキーマ管理、基本的なモデル定義の方法を詳しく解説します。

スキーマファイルの管理方法

単一ファイルでのスキーマ宣言

シンプルなプロジェクトやテーブル数が少ない場合、全てのスキーマを1つのファイルで管理することが一般的です。以下のように、schema.tsファイルにテーブルをまとめて定義することで、シンプルにスキーマを管理できます。

<project root>
└ src
   └ db
      └ schema.ts

また、drizzle.config.tsファイルでスキーマファイルのパスを指定する必要があります。

import { defineConfig } from 'drizzle-kit';
export default defineConfig({
  dialect: 'postgresql', // データベースの種類に応じて指定
  schema: './src/db/schema.ts'
});

複数ファイルでのスキーマ宣言

大規模なプロジェクトやテーブル数が多い場合は、各テーブルごとに別ファイルに分けて管理する方法が便利です。以下のような構成で、各テーブルを個別のファイルに配置できます。

<project root>
└ src
   └ db
      └ schema
         ├ users.ts
         ├ countries.ts
         ├ cities.ts
         └ products.ts

drizzle.config.tsファイルには、スキーマディレクトリ全体を指定することで、自動的にすべてのファイルが読み込まれるようにします。

import { defineConfig } from 'drizzle-kit';
export default defineConfig({
  dialect: 'postgresql', // MySQLやSQLiteも選択可
  schema: './src/db/schema'
});

スキーマ宣言の基本構造

テーブルとカラムの定義

Drizzle ORMでは、テーブルとカラムをデータベースに合わせた型で定義できます。以下は、usersテーブルをPostgreSQL向けに設定する例です。

import { pgTable, serial, varchar, integer } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: varchar('name', { length: 255 }).notNull(),
  age: integer('age').notNull(),
});

カスタム構造の利用

Drizzle ORMはPostgreSQLでのみサポートされる特定機能も備えています。例えば、列挙型(Enums)やシーケンス(Sequences)、ビュー(Views)などを直接定義できます。

列挙型の定義

列挙型は特定の値のみに制限されたカラムに適用できます。以下の例では、ユーザーのステータスを列挙型として定義しています。

import { pgEnum } from 'drizzle-orm/pg-core';
export const userStatus = pgEnum('user_status', ['active', 'inactive', 'suspended']);

シーケンスの利用

IDなどをシーケンスで管理することで、カスタマイズしたインクリメントが可能です。

import { pgSequence, integer } from 'drizzle-orm/pg-core';
export const userIdSeq = pgSequence('user_id_seq');
export const users = pgTable('users', {
  id: integer('id').default(userIdSeq.next()).primaryKey(),
});

スキーマ管理のポイントと注意点

カラム名の自動マッピング

Drizzle ORMではTypeScriptのプロパティ名をデータベースのカラム名として使用しますが、任意で別名を指定することも可能です。これにより、既存のデータベースとの統合が容易になります。

制約の追加

テーブルの制約も定義でき、外部キーやユニーク制約など、データの整合性を確保するためのルールを簡単に設定できます。

import { integer, uniqueIndex } from 'drizzle-orm/pg-core';
export const products = pgTable('products', {
  id: serial('id').primaryKey(),
  name: varchar('name', { length: 255 }).notNull(),
  price: integer('price').notNull(),
}, (products) => ({
  nameIndex: uniqueIndex('name_idx').on(products.name),
}));

まとめ

Drizzle ORMでは、TypeScriptによるデータベーススキーマの柔軟な管理が可能です。単一ファイルや複数ファイルでのスキーマ宣言、各種カラムや制約の設定方法をマスターすることで、型安全性を担保しながらスケーラブルなデータ管理を実現できます。Drizzle Kitを使ってマイグレーションとも連携し、スキーマ変更をコードベースで一貫して管理することが可能です。