prisma 에서 제공하는 기능 중에 model의 둘 이상의 field를 묶어서
1. 그 model의 id(primary key)로 설정하거나
2. uniqueness constraint로 설정하는 기능이 있다.
Composite Id 설정
model User {
id Int @id @default(autoincrement())
name String
post Post[]
likes Like[]
}
model Post {
id Int @id @default(autoincrement())
content String
User User? @relation(fields: [userId], references: [id])
userId Int?
likes Like[]
}
model Like {
postId Int
userId Int
User User @relation(fields: [userId], references: [id])
Post Post @relation(fields: [postId], references: [id])
@@id([postId, userId])
}
이렇게 하면 postId와 userId를 묶어서 Like 테이블의 유니크한 기본 키값으로 설정할 수 있게 된다.
이름도 따로 설정해줄 수 있다.
@@id([postId, userId]) 부분에
@@id(name: "likeId", [postId, userId]) 이렇게 name: "설정할 이름" 을 추가해주면 된다.
Composite Uniqueness Constraint 설정
프로젝트 기획안 설명 중에
"음식점 내에서 동일한 메뉴 이름으로는 재등록이 되지 않습니다." 라는 조건이 있었다.
그런데 하나의 store에서는 menu 이름이 unique 할 지라도 menus 테이블에는 다른 stores 의 menu들도 있고, 서로 다른 store 끼리 menu 이름이 겹칠 수도 있기 때문에
menus 테이블에서 menu 이름에 unique 제약조건을 두지 못하는 문제가 있었다.
그래서 어쩔 수 없이 이를 비즈니스 로직에서만 처리하려고 생각했는데,
다행히도 튜터님 덕분에 prisma 에서 제공하는 기능 중에 composite unique 설정을 할 수 있는 방법이 있다는 것을 알게 되었다.
composite id 설정 방법과 거의 똑같이 하면 된다.
model Menu {
id Int @id @default(autoincrement())
storeId Int @map("store_id")
name String
description String
price Int
image String
totalReviews Int @default(0) @map("total_reviews")
averageRating Float? @map("average_rating")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
store Store @relation(fields: [storeId], references: [id], onDelete: Cascade)
cartItem CartItem[]
orderItem OrderItem[]
reviewMenu ReviewMenu[]
@@unique([storeId, name])
@@map("menus")
}
@@unique([storeId, name])
이렇게 하면 storeId 와 name(메뉴이름)을 묶어서 unique 제약조건을 걸게 되므로
같은 가게에서 같은 메뉴 이름을 등록할 수 없게 된다.
(그렇게 한다면 prisma.menu.create를 할 때 prisma 자체 에러 발생)