岩手アドベントカレンダー
ちょっと今年は過疎ってますが、岩手在住のエンジニアとして参加します。
Prismaで多対多(Many-to-Many)のリレーションを行う
本来、多対多のリレーションを行うに中間テーブルの作成を行う必要があります。
ですが、Prismaでは自動で中間テーブルの作成を行ってくれます。
その他クエリの扱いも楽になるので非常に便利です。
実践
公式ドキュメントを例として記述します。
データモデルの設定
例としてPOSTとCategoryというテーブルを設定します。
それぞれのテーブルにリレーションを追加してあげます。
これでマイグレーションすると_CategoryToPost
というテーブルが自動で作成されます。(_テーブルA To テーブルB
)
model Post {
id Int @id @default(autoincrement())
title String
categories Category[] ←追加
}
model Category {
id Int @id @default(autoincrement())
name String
posts Post[] ←追加
}
実際のマイグレーションファイル
CREATE TABLE "_CategoryToPost" (
"A" integer NOT NULL REFERENCES "Category"(id) ,
"B" integer NOT NULL REFERENCES "Post"(id)
);
CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON "_CategoryToPost"("A" int4_ops,"B" int4_ops);
CREATE INDEX "_CategoryToPost_B_index" ON "_CategoryToPost"("B" int4_ops);
CREATE TABLE "Category" (
id integer SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id integer SERIAL PRIMARY KEY
)
クエリの方法
自動で生成された中間テーブルですが、どのように扱うのでしょうか?
create(connect)
connectを使用することで中間テーブルへ自動で紐づけを行ってくれます。
const newPost = await prisma.post.create({
data: {
title: '新しいポストのタイトル',
categories: {
connect: [
{ id: 1 }, // 既存のカテゴリーID
{ id: 2 } // 別のカテゴリーID
]
}
}
});
Update
updateはsetを使うといいです。setを使用すると、関連付けられたすべての既存のレコードが新しいレコードで置き換えられます。
const newPost = await prisma.post.create({
data: {
title: '新しいポストのタイトル',
categories: {
set: [
{ id: 1 }, // 既存のカテゴリーID
{ id: 2 } // 別のカテゴリーID
]
}
}
});
delete
postレコードの削除によって自動で削除されます。(べんり~)
connect,setってなに?
Prismaで多対多のリレーションシップを扱う際に使用する主要な機能には、connect、disconnect、setなどがあります。これらの機能は、関連するレコード間のリンクを管理するために使用されます。
- connect: 追加する場合
- disconnect: 一部を削除する
- set: 新しいレコードへ置き換える