【Prisma入門】スキーマ定義で使用するデコレーターあれこれ

# はじめに
最近、Prismaを使用する機会が多いので、よく使うデコレーターについてまとめようと思います。
デコレーターというのは「@」で始まるもので、`@id`などのことを言います。

# Prismaの主要なデコレーター
Prismaのデコレーターは`フィールドレベル`のものと`モデルレベル`のものに分かれます。
違いは **@の数**です。

フィールドレベルでは「@」は1つつけますが、モデルレベルでは「@」を2つつけます。

::: note info
フィールドレベルの主要デコレーター
:::

|デコレーター  |解説  |備考|
|-----------|-----|---|
|**@id**     |フィールドを主キーとする| -|
|**@unique**|フィールドにユニーク制約を適用する|-|
|**@default**|フィールドのデフォルト値を設定する|例えば、@default(autoincrement())でIDフィールドが自動的にインクリメントされるように設定できる|
|**@updatedAt**|フィールドの更新日時を自動的に設定する|-|
|**@createdAt**|フィールドの作成日時を自動的に設定する|-|
|**@map**|DBでのフィールド名とPrismaのモデル名が異なる場合にマッピングする|例えば、DBのフィールド名が「user_id」、Prismaのモデル名が「userId」の場合、@map("user_id")とするとマッピングできる|
|**@relation**|2つのモデル間でリレーションを設定できる|例えば、Userモデルとリレーションを組む場合、**@relation(fields: [userId], references: [id], onDelete: Cascade)** と、fieldsに参照されるモデルのフィールド(基本的にはID、この例の場合、PostモデルのuserId)を、referencesに参照先のモデルのフィールド（基本的にはID、この例の場合、Userモデルのid）を設定する。また、オプションとして、onDelete:Cascadeとすることで、親テーブルの関連データが削除されると、子テーブルの関連するデータも削除することができる|
|**@db**|DBの特定の方にマップするために使用する|-|


::: note info
モデルレベルの主要デコレーター
:::

|デコレーター  |解説  |備考|
|-----------|-----|---|
|**@@id**     |複数のフィールドを主キーに設定する| -|
|**@@unique**|複数のフィールドに対してユニーク制約を設定|-|
|**@@index**|複数のフィールドにインデックスを作成する| -|
|**@@map**|DBのテーブル名とPrismaモデル名がことなる場合に使用する|例えば、PrismaモデルUserでテーブル名がusersの場合、@@map("users")とすることでマッピングできる|
|**@@ignore**|Prisma Clientから特定のモデルを除外する|-|

# 使用例

## @id

単一フィールドをIDとして定義。
cuidやuuidをしていすることもできる。
- cuid()
- uuid()


```typescript
model User {
  id  Int  @id @default(autoincrement())
 }
```

## @unique
```typescript
model User {
  email String @unique
  name  String
}
```

```typescript
model User {
  id      Int      @id @default(autoincrement())
  role    Role     @default(USER)
}
```

## @default
```typescript
model User {
  email  String @unique
  number Float  @default(1.1)
}
```

```typescript
model User {
  email  String @unique
  number Decimal @default(22.99)
  createdAt DateTime @default(now())
}
```

```typescript
enum Role {
  USER
  ADMIN
}
```

## @createdAt・@updatedAt
```typescript
model Post {
  id        String   @id
  createdAt DateTime @createdAt
  updatedAt DateTime @updatedAt
}
```

## @map
実際のDBのフィールド名が`name`の場合は以下のように定義する。
```typescript
model Usre {
  userId        String   @id @default(autoincrement()) @map("user_id")
  username @map("name")
}

```

## @relation
```typescript
model Profile {
  authorId Int    @id
  author   User   @relation(fields: [authorId], references: [id])
  bio      String
}

model User {
  id      Int      @id
  email   String   @unique
  name    String?
  profile Profile?
}
```

## @db
```typescript
model User {
  id        Int     @id 
  username  String  @db.VarChar(300)
}
```

## @@id
複合主キーを定義できる。

```typescript
model User {
  firstName String
  lastName  String
  email     String  @unique
  isAdmin   Boolean @default(false)

  @@id([firstName, lastName])
}
```

## @@unique
複合ユニーク属性を定義できる。

```typescript
model User {
  id        Int     @default(autoincrement())
  firstName String
  lastName  String
  isAdmin   Boolean @default(false)

  @@unique([firstName, lastName])
}
```

## @@index
インデックスを指定。
```typescript
model Post {
  id      Int     @id @default(autoincrement())
  title   String
  content String?

  @@index([title])
}
```

```typescript
model Post {
  id      Int     @id @default(autoincrement())
  title   String
  content String?

  @@index([title, content])
}
```

## @@map
実際のDBのテーブル名が`usres`の場合は以下のように定義する。
```typescript
model User {
  id           Int     @id @default(autoincrement())
  name         String?
  writtenPosts Post[]
  pinnedPost   Post?

  @@map('users')
}
```

## @@ignore
SystemLogモデルをPrisma Clientから無視する。
@@ignoreをつけると、そのモデルでPrisma ClientによるCRUD操作ができなくなる。

要するに`prisma.create()`などのメソッドがそのモデルに対して使用できなくなる。
（Prismaで直接操作しなくないモデル（内部的なログやシステムデータなど）に適用する）

```typescript
@@ignore
model SystemLog {
  id        Int      @id @default(autoincrement())
  message   String
  createdAt DateTime @default(now())
}
```

# 参考文献
> -  [Prisma Schemaの書き方あれこれ](https://zenn.dev/ikekyo/scraps/f6c87fbfd3bf9d)
> - [prisma 入門](https://qiita.com/takuyanagai0213/items/70feb3ae695c958b4ecb)