Drizzleの relations() と references() の使い分け
こんにちは、合同会社Stegの keigo です。今回は、Drrizleでテーブルの関係性を定義する方法を紹介します。
Drizzle ORMは、テーブル間の関係性を定義するために、 relations()
とreferences()
という2つの関数を提供しています。
これらの関数は役割が異なるため、注意が必要です。
今回のソースコードは、一部Drizzle公式ドキュメントから引用しています。
relations()
とreferences()
の違い
Drizzle ORMにおいて、relations()
とreferences()
はテーブル間の関係を定義するための同じ目的を持つ関数です。しかし、動作するレベルが異なります。
-
relations()
: アプリケーションレベルで動作し、データベースには影響しない依存関係を設定する -
references()
: データベースレベルで動作し、外部キー制約を設定する
したがって、relations()
のみを使用してテーブル間の関係を定義した場合、drizzle-kit generate
でmigrationファイルを生成しようとしても、スキーマは変更が生じていないと判定されます。そのため、migrationファイルは生成されません。
relations()
を使用したテーブル間の関係性定義
relations()
関数では、アプリケーションレベルでの依存関係を定義し、データベース側には影響しません。そのため、外部キーに対応していないDBでも、テーブルの関係性を定義することができます。
また、テーブル間の1対1や1対多、多対多といった関係性を宣言するために、one()
関数やmany()
関数を使用します。
次のコードは、以下の条件を表しています。
-
users
テーブルとposts
が1対多 (posts
がnullの可能性あり) -
posts
テーブルとusers
が1対1 (posts.author_id
とusers.id
が紐づいている)
import { pgTable, serial, text, integer } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name'),
});
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
content: text('content'),
authorId: integer('author_id'),
});
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id],
}),
}));
references()
を使用したテーブル間の関係性定義
references()
関数を使用することで、外部キーを設定することができます。
以下のコードでは、users
テーブルのidとprofile_info
テーブルのuser_id
の関係性を表しています。
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name'),
});
export const profileInfo = pgTable('profile_info', {
id: serial('id').primaryKey(),
userId: integer("user_id").references(() => users.id),
metadata: jsonb("metadata"),
});
上記の定義により、users.id
とprofile_info.user_id
に対して外部キー制約が設定されます。
生成されたSQLは以下のとおりです。
CREATE TABLE IF NOT EXISTS "profile_info" (
"id" serial PRIMARY KEY NOT NULL,
"user_id" integer,
"metadata" jsonb
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "users" (
"id" serial PRIMARY KEY NOT NULL,
"name" text
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "profile_info" ADD CONSTRAINT "profile_info_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
おわりに
今回は、Drizzle ORMを使用してテーブル間の関連を定義する方法を紹介しました。
relations()
やreferences()
に関する詳細は、Drizzle ORM公式ドキュメントをご覧ください。
Discussion