過去に少しハマったので、備忘録として残しておきます。
prisma is 何 ?
TypeScriptのORMです。
公式はこちら
https://www.prisma.io/
構成
例えばeラーニングの様なサイトを作っているとします。
システムには受講者と講座が必要なので、それぞれ受講者テーブル(User)と 講座テーブル(Course)を用意します。
Userテーブル
id | nickname |
1 | 太郎 |
2 | 花子 |
Courseテーブル
id | name |
1 | 国語 |
2 | 算数 |
3 | 理科 |
4 | 社会 |
UserOnCoursesテーブル
id | userId | courseId |
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
4 | 2 | 1 |
5 | 2 | 2 |
6 | 2 | 4 |
中間テーブルのUserOnCoursesを用意します。
受講者側から見ると
太郎くん→「国語」と「算数」と「理科」を受講します。
花子さん→「国語」と「算数」と「社会」を受講します。
講座側から見ると
国語→「太郎」くんと「花子」さんに受講されます。
算数→「太郎」くんと「花子」さんに受講されます。
理科→「太郎」くんに受講されます。
社会→「花子」さんに受講されます。
受講者は複数の講座(対多)を受講し、講座も複数のユーザー(対多)に受講されます。
よって「User」と「Course」が多対多の関係になっており、それを中間テーブル「UserOnCourses」によって関連づけられています。
schema.prismaは下記のようになっています。
// schema.prisma
model User {
id Int @id @default(autoincrement())
nickname String
・
・
・
courses UserOnCourses[]
}
model Course {
id Int @id @default(autoincrement())
name String
・
・
・
users UserOnCourses[]
}
model UserOnCourses {
user User @relation(fields: [userId], references: [id])
userId Int
course Course @relation(fields: [courseId], references: [id])
courseId Int
@@id([userId, courseId])
}
やりたいこと
国語の受講者を全員取得したい
// TypeScript
const users = await this.prisma.user.findMany({
select: {
id: true,
/**
* ・
* ・
* ・
*/
},
where: {
courses: {
some: {
courseId: {
equals: 1 // Courseテーブルの国語のid,
},
},
},
},
})
これで、国語を受講している太郎くんと花子さんの二人が取得されます。
因みに実際に発行されるSQLはこんな感じ
SELECT
u."id"
FROM
"User" AS u
WHERE (
(u.id) IN (
SELECT
u1."id"
FROM
"User" AS u1
INNER JOIN "UserOnCourses" AS uoc
ON (uoc."userId") = (u1."id")
WHERE (
uoc."courseId" = 1 AND
u1."id" IS NOT NULL
)
))
;
以上