Prismaで自己リレーション(self relation)を設計していると、特に複数の自己リレーションを持つ場合に必ずと言っていいほどハマるポイントがあります。私はハマりました。
この記事では、Prisma特有の仕様と、正しい自己リレーション設計の仕方を解説します。
自己リレーションとは?
自己リレーションとは、同じテーブルのレコード同士が関連する構造のこと。
例えば:
- フォルダの親子階層(親フォルダ → 子フォルダ)
- 組織の上司と部下の関係
- カテゴリー分類の階層構造
といったツリー構造や関連構造を表現する際によく使います。
Prismaの自己リレーション:1つの場合はシンプル
Prismaで自己リレーションが1つだけの場合は、片方向の定義だけで成立します。
model Node {
id Int @id @default(autoincrement())
parentId Int?
parent Node? @relation(fields: [parentId], references: [id])
}
この場合、Prismaは片方向だけでも自動でリレーションを解釈してくれます。
複数の自己リレーションを定義するとき
自己リレーションが2つ以上ある場合は要注意。何も考えずに定義すると下記のようなエラーが出ます:
Error validating: Ambiguous self relation on model `Node`. Please provide a relation name to disambiguate.
Prisma「どっちのリレーションか判別できないよーん!」
この原因は:
- @relation名が未指定
- 片方向しか定義していない
これがPrismaの自己リレーション特有の制約です。
正しい自己リレーションの設計(複数リレーション版)
複数の自己リレーションを設計する場合は、
- @relation名の明示
- 両方向(親→子、子→親)の記述
が必須です。
設計例
model Node {
id Int @id @default(autoincrement())
parentId Int?
parent Node? @relation("ParentRelation", fields: [parentId], references: [id])
children Node[] @relation("ParentRelation")
relatedNodeId Int?
relatedNode Node? @relation("RelatedRelation", fields: [relatedNodeId], references: [id])
relatedNodes Node[] @relation("RelatedRelation")
}
設計のポイント
フィールド | relation名 | 役割 |
---|---|---|
parentId / parent | "ParentRelation" | 親ノード(単体)への参照 |
children | "ParentRelation" | 子ノード(複数)への参照 |
relatedNodeId / relatedNode | "RelatedRelation" | 関連ノード(単体)への参照 |
relatedNodes | "RelatedRelation" | 関連ノード(複数)への参照 |
まとめ
- Prismaの自己リレーションは、1つだけなら片方向だけでOK
- 複数ある場合は両方向にリレーションと@relation名を必ず指定
- 指定しないと
Ambiguous self relation
エラーになる
Prismaの自己リレーションは型安全なコード生成のために明確なマッピングが必須なので、このルールを覚えておけばもう怖くありません!
参照
株式会社シンシア
株式会社xincereでは、実務未経験のエンジニアの方や学生エンジニアインターンを採用し一緒に働いています。
※ シンシアにおける働き方の様子はこちら
シンシアでは、年間100人程度の実務未経験の方が応募し技術面接を受けます。
その経験を通し、実務未経験者の方にぜひ身につけて欲しい技術力(文法)をここでは紹介していきます。