過去に少しハマったので、備忘録として残しておきます。
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
    )
  ))
;
以上
	
      

