一對多關係
本頁面介紹一對多關係,並說明如何在您的 Prisma Schema 中使用它們。
概觀
一對多 (1-n) 關係指的是在關係的一側的一個記錄可以連接到另一側的零個或多個記錄的關係。在以下範例中,User
和 Post
模型之間存在一對多關係
- 關聯式資料庫
- MongoDB
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
}
注意
posts
欄位不會在底層資料庫結構描述中「顯現」。在關係的另一側,已註解的關聯欄位author
及其關聯純量authorId
代表關係的哪一側在底層資料庫中儲存外鍵。
此一對多關係表達以下內容
- 「一個使用者可以有零個或多個貼文」
- 「一個貼文必須始終有一個作者」
在先前的範例中,Post
模型的 author
關聯欄位參考 User
模型的 id
欄位。您也可以參考不同的欄位。在這種情況下,您需要使用 @unique
屬性標記欄位,以保證只有一個 User
連接到每個 Post
。在以下範例中,author
欄位參考 User
模型中的 email
欄位,該欄位已使用 @unique
屬性標記
- 關聯式資料庫
- MongoDB
model User {
id Int @id @default(autoincrement())
email String @unique // <-- add unique attribute
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
authorEmail String
author User @relation(fields: [authorEmail], references: [email])
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique // <-- add unique attribute
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
authorEmail String
author User @relation(fields: [authorEmail], references: [email])
}
在 MySQL 中,您可以僅使用參考側的索引來建立外鍵,而不是唯一約束。在 Prisma ORM 4.0.0 及更新版本中,如果您內省這種關係,它會觸發驗證錯誤。若要修正此問題,您需要將 @unique
約束新增至參考欄位。
關聯式資料庫中的多欄位關係
在僅限關聯式資料庫中,您也可以使用多欄位 ID/複合鍵定義此關係
model User {
firstName String
lastName String
post Post[]
@@id([firstName, lastName])
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorFirstName, authorLastName], references: [firstName, lastName])
authorFirstName String // relation scalar field (used in the `@relation` attribute above)
authorLastName String // relation scalar field (used in the `@relation` attribute above)
}
資料庫中的 1-n 關係
關聯式資料庫
以下範例示範如何在 SQL 中建立 1-n 關係
CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"authorId" integer NOT NULL,
FOREIGN KEY ("authorId") REFERENCES "User"(id)
);
由於 authorId
欄位(外鍵)上沒有 UNIQUE
約束,因此您可以建立多個指向同一個 User
記錄的 Post
記錄。這使得關係成為一對多關係,而不是一對一關係。
以下範例示範如何在 SQL 中使用複合鍵 (firstName
和 lastName
) 建立 1-n 關係
CREATE TABLE "User" (
firstName TEXT,
lastName TEXT,
PRIMARY KEY ("firstName","lastName")
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"authorFirstName" TEXT NOT NULL,
"authorLastName" TEXT NOT NULL,
FOREIGN KEY ("authorFirstName", "authorLastName") REFERENCES "User"("firstName", "lastName")
);
比較一對一和一對多關係
在關聯式資料庫中,1-1 和 1-n 關係之間的主要區別在於,在 1-1 關係中,外鍵必須定義 UNIQUE
約束。
MongoDB
對於 MongoDB,Prisma ORM 目前使用標準化資料模型設計,這表示文件透過 ID 互相參考,方式與關聯式資料庫類似。
以下 MongoDB 文件代表 User
{ "_id": { "$oid": "60d5922d00581b8f0062e3a8" }, "name": "Ella" }
以下每個 Post
MongoDB 文件都有一個 authorId
欄位,該欄位參考同一個使用者
[
{
"_id": { "$oid": "60d5922e00581b8f0062e3a9" },
"title": "How to make sushi",
"authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
},
{
"_id": { "$oid": "60d5922e00581b8f0062e3aa" },
"title": "How to re-install Windows",
"authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
}
]
比較一對一和一對多關係
在 MongoDB 中,1-1 和 1-n 之間唯一的區別是資料庫中參考另一個文件的文件數量 - 沒有約束。
一對多關係中必要和可選的關聯欄位
1-n 關係始終有兩個關聯欄位
1-n 關係的已註解關聯欄位和關聯純量可以都是可選的,或者都是必要的。在關係的另一側,清單始終是必要的。
可選的一對多關係
在以下範例中,您可以建立 Post
而無需指派 User
- 關聯式資料庫
- MongoDB
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
author User? @relation(fields: [authorId], references: [id])
authorId String? @db.ObjectId
}
必要的一對多關係
在以下範例中,您必須在建立 Post
時指派 User
- 關聯式資料庫
- MongoDB
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
}