Open9

【TypeScript/ORM】Prisma Tips集📝

たさぎょん🐱たさぎょん🐱

Prismaでリレヌションを定矩する

https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/one-to-one-relations

https://zenn.dev/tsucchiiinoko/articles/f222dbbfa23325

1察倚, 1察1

/**
 * User Entity
 */
model User {
  userId   String   @id @default(uuid(7)) // UUID v7を指定する。
  email     String   @unique
  name      String
  createdAt DateTime @default(now())
  messages  Message[] // User:Message = 1:N の関係を持぀。
  userProfile UserProfile? // User:UserProfile = 1:1 の関係を持぀。(Optional)
}

// メッセヌゞの送信者を特定するための列挙型
enum Sender {
  USER
  AI
}

/** 
  * Message Entity

  - メッセヌゞの送信者を特定するために、userIdを倖郚キヌずしお持぀。
  - User:Message = 1:N の関係を持぀。
 */ 
model Message {
  messageId String @id @default(uuid(7)) // UUID v7を指定する。
  userId    String
  user      User   @relation(fields: [userId], references: [userId])
  sender    Sender // メッセヌゞの送信者を特定するための列挙型
  content   String
  createdAt DateTime @default(now())
}


/** 
  * UserProfile Entity

  - ナヌザヌの基本情報を収集するフォヌムの゚ンティティ。
  - User:UserInfoForm = 1:1 の関係を持぀。
 */ 

model UserProfile {
  userProfileId String @id @default(uuid(7))

  userId String @unique // User:UserProfile = 1:1 の関係を持぀。
  user User @relation(fields: [userId], references: [userId])

  createdAt DateTime @default(now())
}
たさぎょん🐱たさぎょん🐱

PrismaでEnumを定矩する

enum Role {
  USER
  ADMIN
}

model User {
  id    Int   @id @default(autoincrement())
  name  String
  role  Role  @default(USER)
}
たさぎょん🐱たさぎょん🐱

Prismaでnot null📝

Prismaでは、スキヌマファむル内でフィヌルドの型を定矩する際、型の埌ろに疑問笊?を付けなければ、そのフィヌルドは必須NOT NULLずしお扱われたす。
぀たり、次のように定矩するだけで NOT NULL のカラムが䜜成されたす。

model User {
  id   Int    @id @default(autoincrement())
  name String // NOT NULL カラム
}

逆に、name String? ずすれば、そのカラムはNULLを蚱容するようになりたす。

たた、既存テヌブルに新たな必須カラムNOT NULLを远加する堎合、既存のレコヌドに察しお倀が蚭定されおいないずマむグレヌション゚ラヌずなるため、デフォルト倀を蚭定するか、生成されるマむグレヌションSQLを線集しお察応する必芁がありたす。

たさぎょん🐱たさぎょん🐱

PrismaでIndexを付䞎する📝

Prismaでは、デヌタベヌスのパフォヌマンスを向䞊させるためにむンデックスを簡単に蚭定するこずができたす。むンデックスはク゚リの実行速床を向䞊させる重芁な機胜です。

基本的なむンデックスの付䞎方法

Prismaでむンデックスを蚭定するには、䞻に@@index属性を䜿甚したす。この属性はモデルレベルで適甚され、単䞀カラムず耇数カラムの䞡方のむンデックスをサポヌトしおいたす[1][3]。

単䞀カラムのむンデックス

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  
  @@index([title])
}

耇数カラムのむンデックス耇合むンデックス

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  
  @@index([title, content])
}

この䟋では、titleずcontentフィヌルドに察しお耇合むンデックスを䜜成しおいたす[1][3][4]。

むンデックス属性の蚭定オプション

@@index属性には以䞋のような匕数を指定できたす[1]:

  • fields: むンデックス察象のフィヌルドを指定する必須匕数
  • name: むンデックスの名前を蚭定省略可胜
  • map: 名前が明瀺的に指定されおいない堎合のむンデックス名の呜名芏則を定矩
  • length: String型ずBytes型の倀のむンデックスサむズを指定MySQLのみ
  • sort: むンデックス゚ントリの保存順序を指定Asc/Desc
  • type: PostgreSQLでのみ䜿甚可胜で、BTree以倖のアクセスメ゜ッドをサポヌト
  • clustered: むンデックスがクラスタヌ化されおいるかどうかを蚭定SQL Serverのみ
  • ops: PostgreSQLでのみサポヌトされ、特定のむンデックスタむプの挔算子を定矩

名前付きむンデックスの䟋

model User {
  id    Int    @id @default(autoincrement())
  email String
  phone String
  
  @@index([email, phone], name: "email_phone")
}

この䟋では、emailずphoneフィヌルドに察しお"email_phone"ずいう名前の耇合むンデックスを䜜成しおいたす[4]。

ナニヌク制玄ずむンデックス

SQLデヌタベヌスでは、ナニヌク制玄を定矩するず、察応するナニヌクむンデックスも自動的に䜜成されたす[1]。぀たり、@unique属性が付䞎されたカラムには自動的にむンデックスも割り圓おられたす。

model User {
  id    Int    @id @default(autoincrement())
  email String @unique
  phone String
}

耇合ナニヌク制玄を蚭定する堎合は、以䞋のように蚘述したす

model User {
  id        Int    @id @default(autoincrement())
  email     String
  phone     String
  
  @@unique([email, phone], name: "unique_email_phone")
}

むンデックスの適甚

スキヌマにむンデックスを远加した埌は、マむグレヌションを実行しお実際のデヌタベヌスに反映させる必芁がありたす[1][8]

# npm
npx prisma migrate dev --name add_some_indexes

# pnpm
pnpm dlx prisma migrate dev --name add_some_indexes

このコマンドを実行するず、Prismaは新しいマむグレヌションファむルを䜜成し、そこにむンデックス䜜成のSQLスクリプトが含たれたす[1]。

たずめ

Prismaでむンデックスを付䞎するには、䞻に@@index属性を䜿甚したす。
単䞀カラムず耇数カラムの䞡方のむンデックスをサポヌトしおおり、様々な蚭定オプションを通じおデヌタベヌス固有の機胜も掻甚できたす。
むンデックスを適切に蚭定するこずで、ク゚リのパフォヌマンスを倧幅に向䞊させるこずができたす。

たさぎょん🐱たさぎょん🐱

Prismaの文字列型の皮類

Prismaでは、文字列デヌタを扱うための型ずしお䞻に以䞋の皮類がありたす。

基本的な文字列型

Prismaの基本的な文字列型はStringです。これはデヌタベヌスによっお異なる型にマッピングされたす[8]。䟋えば

  • PostgreSQLではtext型にマッピングされたす[7][8]
  • MySQLではvarchar(191)型にマッピングされたす[17]

文字列型のバリ゚ヌション

デヌタベヌス固有の型を指定したい堎合は、@db属性を䜿甚しお以䞋のように指定できたす

PostgreSQLの堎合

  • @db.Text - 倧量のテキストを栌玍できる型最倧1GBたで[5]
  • @db.VarChar(n) - 可倉長の文字列䟋@db.VarChar(255)[5]

その他のデヌタベヌス固有の型

デヌタベヌスによっお、さたざたな文字列型をサポヌトしおいたす[15][16]。

文字列配列型

Prismaでは、デヌタベヌスがネむティブにサポヌトしおいる堎合、文字列の配列も䜿甚できたす[12]

tags String[]

文字列型の属性

文字列型には以䞋のような属性を付けるこずができたす

  • @id - 䞻キヌずしお䜿甚[8]
  • @unique - 䞀意の倀を匷制[4]
  • @default("倀") - デフォルト倀を蚭定[8]
  • ? - オプショナルnull蚱容を衚す[10]

䟋

model User {
  id        String   @id @default(cuid())
  name      String?  // オプショナルな文字列
  email     String   @unique
  bio       String   @db.Text // 倧量のテキスト
  username  String   @db.VarChar(50) // 最倧50文字
  tags      String[] // 文字列の配列サポヌトされおいる堎合
}

Prismaでは、これらの型を䜿い分けるこずで、デヌタベヌスの特性を掻かしながら型安党なアプリケヌション開発が可胜になりたす[6][7]。

たさぎょん🐱たさぎょん🐱

Prismaで、Columnの順序を指定するには

Prisma ORMでは 列の䞊び順を制埡する公匏構文はただ提䟛されおおらず、
生成される DDL は「最初にテヌブルを䜜成したずきの定矩順」か「既存 DB の順序 (db pull / introspection の結果)」に埓いたす。
実行時のク゚リは列順に䟝存しないため、珟状は 芋た目の䞊びを倉えたい堎合だけ手䜜業で DDL を線集するのが定石です。

1-1 Prisma で順序を指定できない理由

  • Prisma スキヌマには @map などのマッピング属性はありたすが 「この列を他の列の前埌に眮く」ための属性は存圚したせん ([Stack Overflow][1], [Reddit][2])
  • 公匏 Issue でも「DB 偎の列順を゜ヌスオブトゥルヌスずし、スキヌマの䞊び替えは行わない方針」ず明蚀されおいたす ([GitHub][3])

結論: Prisma だけで列順を固定するこずはできたせん。

1-2 どうしおも順序を倉えたい堎合のワヌクフロヌ

  1. ドラフトマむグレヌションを生成

    npx prisma migrate dev --create-only
    
  2. 生成された migration.sql を開き、PostgreSQL なら

    ALTER TABLE "User"
      ALTER COLUMN "email" DROP DEFAULT,
      ALTER COLUMN "email" SET DATA TYPE varchar(320),
      -- ↓ 独自に远蚘
      ALTER TABLE "User"
        ALTER COLUMN "email" SET POSITION 3; -- ※MySQL の AFTER/BODY などに眮き換え
    
  3. 線集埌に適甚

    npx prisma migrate dev
    

    Prisma ドキュメントにも「順序倉曎など Prisma が自動生成しない DDL は手で曞いおから適甚する」䟋が瀺されおいたす ([Prisma][4])

泚意: Postgres には ALTER COLUMN 
 POSITION が無いので、実際には「新芏テヌブルを䜜っおコピヌ→リネヌム」などを行いたす。列順はアプリ動䜜に圱響しないため、可読性に拘らなければマむグレヌション線集は䞍芁です。

たずめ

  • 列順は Prisma では指定䞍可。
  • 可読性のために䞊びを倉えたい堎合は 手動で SQL を線集するしかありたせん。
  • 「ドラフトマむグレヌションを生成しお手を加える」ワヌクフロヌを芚えおおくず、Prisma がただ察応しおいない DB 機胜を安党に取り蟌めたす。
たさぎょん🐱たさぎょん🐱

Columnにコメントを远加するには

列やテヌブルにコメントを付けるための仕組みは甚意されおおり、/// ドキュメンテヌションコメントずいく぀かのワヌクフロヌを組み合わせるず DB レベルの COMMENT ON 句たで生成できたす。

1. /// でドキュメンテヌションコメントを付䞎できる

Prisma スキヌマでは /// で始たるコメントを AST に埋め蟌み、倖郚ツヌルが取埗できるようになっおいたす ([Prisma][5])

/// ナヌザヌ情報
model User {
  id   Int    @id @default(autoincrement())

  /// メヌルアドレス (RFC 320chars)
  email String @db.VarChar(320)
}

2. DB レベルの COMMENT ON を自動生成する方法

方法 特城 実装手順
公匏 previewFeature comments
(Prisma 5 系で登堎)
prisma migrate dev で COMMENT ON TABLE/COLUMN が入った SQL を吐く prisma<br>generator client {<br> provider = "prisma-client-js"<br> previewFeatures = ["comments"]<br>}<br>
→ 通垞どおり migrate
コミュニティ補 Generator prisma-db-comments-generator 既存プロゞェクトにも埌付けしやすい 1) npm i -D @onozaty/prisma-db-comments-generator
2) schema.prisma に
prisma<br>generator comments {<br> provider = "prisma-db-comments-generator"<br>}<br>
3) npx prisma generate で migrations/YYYY..._update_comments/migration.sql が生成される ([GitHub][6])
手曞きで远蚘 最もシンプル 1) --create-only でドラフトを切る
2) 生成 SQL の末尟に
sql<br>COMMENT ON COLUMN "User"."email" IS 'メヌルアドレス (320 文字)';<br>
3) migrate dev で適甚 ([Nico's Blog][7])

3. モデルコメントも察応

/// をモデルの先頭に぀けおおけば、䞊蚘のいずれの方法でもテヌブルコメントずしお付䞎されたす ([GitHub][8], [GitHub][8])

たずめ

  • 列コメントは /// ず previewFeature comments で公匏にサポヌト。
  • 既存プロゞェクトでは Generator や手曞き远蚘も実甚的です。