今天我們要來繼續講 relation
在 prisma
中總共有三種 relation type
:
以下方的例子為例
model User {
id Int @id @default(autoincrement())
posts Post[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id])
userId Int @unique // relation scalar field (used in the `@relation` attribute above)
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorId], references: [id])
authorId Int // relation scalar field (used in the `@relation` attribute above)
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
posts Post[]
}
彼此的關聯圖如下,接下來的幾天我們將更深入瞭解 relation
在 prisma
中的實作
One-to-one (1-1) relations
代表著是一個 record
可以關聯到另外一個 model
的 relation
,如以下的範例,一個 User
只會有一個 profile
,同時你會看到因為 ?
的關係 profile
是 optional
,所以 User
可以沒有 Profile
。
model User {
id Int @id @default(autoincrement())
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id])
userId Int @unique // relation scalar field (used in the `@relation` attribute above)
}
在 User.userId
他代表著是一個 scalar type
,對於 SQL
來說是一個 foreign key
以上一個範例來說 user.id
關聯 Profile.userId
,但其實你不一定要這樣關聯,只要其他的欄位確保是 unique
就 ok
,所以我們在 User
加上 unique
的 email
,然後調整 Profile.user
的 relation
去 references
到 User.email
,因為 @unique
關係,一個 User
只會有一個 email
,所以也可以保證 User.profile
的唯一性
model User {
id Int @id @default(autoincrement())
email String @unique // <-- add unique attribute
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userEmail], references: [email])
userEmail String @unique // relation scalar field (used in the `@relation` attribute above)
}
另一個比較有趣的是,我們不一定只能透過 id
來當作 record
的唯一性,除了上面看到的 @unique
以外你也可以透過 composite id
的方式,讓兩個 filed
具備唯一性的特點,這邊我們打算以 firstName
跟 lastName
為例
model User {
firstName String
lastName String
profile Profile?
@@id([firstName, lastName])
}
model Profile {
id Int @id @default(autoincrement())
user User @relation(fields: [userFirstName, userLastName], references: [firstName, lastName])
userFirstName String // relation scalar field (used in the `@relation` attribute above)
userLastName String // relation scalar field (used in the `@relation` attribute above)
@@unique([userFirstName, userLastName])
}
另外這邊要注意的是 Profile
也需要確保 @relation.fields
也是 unique
的這樣關聯起來的資料才不會有重複的情況
以上面 userId
的範例來說在 SQL
會長這樣,這邊要注意的是如果你是透過 SQL
直接 create table
的話,記得 userId
要加上 UNIQUE
否則會被認為是一對多的關係~
CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Profile" (
id SERIAL PRIMARY KEY,
"userId" INTEGER NOT NULL UNIQUE,
FOREIGN KEY ("userId") REFERENCES "User"(id)
);
那如果是 firstName + lastName
當 id
的範例 SQL
如下,一樣因為是一對一的關係要記得加上 UNIQUE
CREATE TABLE "User" (
firstName TEXT,
lastName TEXT,
PRIMARY KEY ("firstName","lastName")
);
CREATE TABLE "Profile" (
id SERIAL PRIMARY KEY,
"userFirstName" TEXT NOT NULL,
"userLastName" TEXT NOT NULL,
UNIQUE ("userFirstName", "userLastName")
FOREIGN KEY ("userFirstName", "userLastName") REFERENCES "User"("firstName", "lastName")
);
在一對一的情況中,如果你的 User model
沒有加上 @relation
欄位,你關聯的 filed
只能是 ?
optional
model User {
id Int @id @default(autoincrement())
profile Profile? // No relation scalar - must be optional
}
那如果你要強制 User
一定要有一個 profile
則必須要加上 @relation
,如此在 create user
的時候,只必須要關聯到一筆 profile
model User {
id Int @id @default(autoincrement())
profile Profile @relation(fields: [profileId], references: [id]) // references `id` of `Profile`
profileId Int @unique // relation scalar field (used in the `@relation` attribute above)
}
model Profile {
id Int @id @default(autoincrement())
user User?
}
也或者 @relation
可以加上 ?
這樣當你 create user
也不會強制你要 connect
到 profile
model User {
id Int @id @default(autoincrement())
profile Profile? @relation(fields: [profileId], references: [id]) // references `id` of `Profile`
profileId Int? @unique // relation scalar field (used in the `@relation` attribute above)
}
model Profile {
id Int @id @default(autoincrement())
user User?
}
最後補充一個概念就是,因為是一對一的關西,今天你要定義 @relation
在哪個 model
都可以,沒有一定的答案,全看你怎麼設計
model User {
id Int @id @default(autoincrement())
profile Profile?
}
model Profile{
id Int @id @default(autoincrement())
user User @relation(fileds:[userId],reference:[id])
userId Int @unique
}
model User {
id Int @id @default(autoincrement())
profile Profile? @relation(fields: [profileId], references: [id])
profileId Int? @unique // relation scalar field (used in the `@relation` attribute above)
}
model Profile {
id Int @id @default(autoincrement())
user User?
}
✅ 前端社群 :
https://lihi3.cc/kBe0Y