跳到主要內容

自關聯

關聯欄位也可以引用其自身模型,在這種情況下,此關聯被稱為自關聯。自關聯可以是任意基數,例如一對一、一對多和多對多。

請注意,自關聯始終需要 @relation 屬性。

一對一自關聯

以下示例建立了一對一自關聯模型

model User {
id Int @id @default(autoincrement())
name String?
successorId Int? @unique
successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id])
predecessor User? @relation("BlogOwnerHistory")
}

此關聯表示以下內容

  • "一個使用者可以有一個或零個前任"(例如,Sarah 是 Mary 作為部落格所有者的前任)
  • "一個使用者可以有一個或零個繼任者"(例如,Mary 是 Sarah 作為部落格所有者的繼任者)

注意:一對一自關聯不能在兩端都設為必填。一端或兩端必須是可選的,否則將無法建立第一個 User 記錄。

建立一對一自關聯

  • 關聯的兩端都必須定義一個具有相同名稱的 @relation 屬性——在本例中,為 BlogOwnerHistory
  • 一個關聯欄位必須是完全註解的。在本例中,successor 欄位定義了 fieldreferences 兩個引數。
  • 一個關聯欄位必須由外部索引鍵支援。successor 欄位由 successorId 外部索引鍵支援,該外部索引鍵引用 id 欄位中的值。successorId 標量關聯欄位還需要一個 @unique 屬性來保證一對一關聯。

注意:一對一自關聯即使關係的兩端相等,也需要兩個方面。例如,要建模“最好的朋友”關聯,你需要建立兩個關聯欄位:bestfriend1bestfriend2

關聯的任一端都可以由外部索引鍵支援。在下面重複的先前示例中,successorsuccessorId 支援

model User {
id Int @id @default(autoincrement())
name String?
successorId Int? @unique
successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id])
predecessor User? @relation("BlogOwnerHistory")
}

或者,你可以重寫它,使 predecessorpredecessorId 支援

model User {
id Int @id @default(autoincrement())
name String?
successor User? @relation("BlogOwnerHistory")
predecessorId Int? @unique
predecessor User? @relation("BlogOwnerHistory", fields: [predecessorId], references: [id])
}

無論哪一側由外部索引鍵支援,Prisma Client 都會顯示 predecessorsuccessor 欄位

const x = await prisma.user.create({
data: {
name: "Bob McBob",
successor: {
connect: {
id: 2,
},
},
predecessor: {
connect: {
id: 4,
},
},
},
});

資料庫中的一對一自關聯

關係型資料庫

僅在關係型資料庫中,一對一自關聯由以下 SQL 表示

CREATE TABLE "User" (
id SERIAL PRIMARY KEY,
"name" TEXT,
"successorId" INTEGER
);

ALTER TABLE "User" ADD CONSTRAINT fk_successor_user FOREIGN KEY ("successorId") REFERENCES "User" (id);

ALTER TABLE "User" ADD CONSTRAINT successor_unique UNIQUE ("successorId");

MongoDB

對於 MongoDB,Prisma ORM 當前使用規範化資料模型設計,這意味著文件透過 ID 相互引用,與關係型資料庫類似。

以下 MongoDB 文件表示兩個使用者之間的一對一自關聯

{ "_id": { "$oid": "60d97df70080618f000e3ca9" }, "name": "Elsa the Elder" }
{
"_id": { "$oid": "60d97df70080618f000e3caa" },
"name": "Elsa",
"successorId": { "$oid": "60d97df70080618f000e3ca9" }
}

一對多自關聯

一對多自關聯如下所示

model User {
id Int @id @default(autoincrement())
name String?
teacherId Int?
teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id])
students User[] @relation("TeacherStudents")
}

此關聯表示以下內容

  • "一個使用者有零個或一個老師"
  • "一個使用者可以有零個或多個學生"

請注意,你也可以透過將 teacher 欄位設定為必填來要求每個使用者都有一位老師。

資料庫中的一對多自關聯

關係型資料庫

在關係型資料庫中,一對多自關聯由以下 SQL 表示

CREATE TABLE "User" (
id SERIAL PRIMARY KEY,
"name" TEXT,
"teacherId" INTEGER
);

ALTER TABLE "User" ADD CONSTRAINT fk_teacherid_user FOREIGN KEY ("teacherId") REFERENCES "User" (id);

請注意 teacherId 上沒有 UNIQUE 約束——多個學生可以有同一個老師。

MongoDB

對於 MongoDB,Prisma ORM 當前使用規範化資料模型設計,這意味著文件透過 ID 相互引用,與關係型資料庫類似。

以下 MongoDB 文件表示三個使用者之間的一對多自關聯——一個老師和兩個具有相同 teacherId 的學生

{
"_id": { "$oid": "60d9b9e600fe3d470079d6f9" },
"name": "Ms. Roberts"
}
{
"_id": { "$oid": "60d9b9e600fe3d470079d6fa" },
"name": "Student 8",
"teacherId": { "$oid": "60d9b9e600fe3d470079d6f9" }
}
{
"_id": { "$oid": "60d9b9e600fe3d470079d6fb" },
"name": "Student 9",
"teacherId": { "$oid": "60d9b9e600fe3d470079d6f9" }
}

多對多自關聯

多對多自關聯如下所示

model User {
id Int @id @default(autoincrement())
name String?
followedBy User[] @relation("UserFollows")
following User[] @relation("UserFollows")
}

此關聯表示以下內容

  • "一個使用者可以被零個或多個使用者關注"
  • "一個使用者可以關注零個或多個使用者"

請注意,對於關係型資料庫,這種多對多關聯是隱式的。這意味著 Prisma ORM 會在底層資料庫中為其維護一個關聯表

如果你需要關聯包含其他欄位,你也可以建立一個顯式的多對多自關聯。前面顯示的自關聯的顯式版本如下

model User {
id Int @id @default(autoincrement())
name String?
followedBy Follows[] @relation("followedBy")
following Follows[] @relation("following")
}

model Follows {
followedBy User @relation("followedBy", fields: [followedById], references: [id])
followedById Int
following User @relation("following", fields: [followingId], references: [id])
followingId Int

@@id([followingId, followedById])
}

資料庫中的多對多自關聯

關係型資料庫

在關係型資料庫中,多對多自關聯(隱式)由以下 SQL 表示

CREATE TABLE "User" (
id integer DEFAULT nextval('"User_id_seq"'::regclass) PRIMARY KEY,
name text
);
CREATE TABLE "_UserFollows" (
"A" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE,
"B" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE
);

MongoDB

對於 MongoDB,Prisma ORM 當前使用規範化資料模型設計,這意味著文件透過 ID 相互引用,與關係型資料庫類似。

以下 MongoDB 文件表示五個使用者之間的多對多自關聯——其中兩位使用者關注了 "Bob",另有兩位使用者 "Bob" 也關注了他們

{
"_id": { "$oid": "60d9866f00a3e930009a6cdd" },
"name": "Bob",
"followedByIDs": [
{ "$oid": "60d9866f00a3e930009a6cde" },
{ "$oid": "60d9867000a3e930009a6cdf" }
],
"followingIDs": [
{ "$oid": "60d9867000a3e930009a6ce0" },
{ "$oid": "60d9867000a3e930009a6ce1" }
]
}
{
"_id": { "$oid": "60d9866f00a3e930009a6cde" },
"name": "Follower1",
"followingIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }]
}
{
"_id": { "$oid": "60d9867000a3e930009a6cdf" },
"name": "Follower2",
"followingIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }]
}
{
"_id": { "$oid": "60d9867000a3e930009a6ce0" },
"name": "CoolPerson1",
"followedByIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }]
}
{
"_id": { "$oid": "60d9867000a3e930009a6ce1" },
"name": "CoolPerson2",
"followedByIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }]
}

在同一模型上定義多個自關聯

你也可以在同一模型上一次性定義多個自關聯。以前面各節中的所有關聯為例,你可以如下定義一個 User 模型

model User {
id Int @id @default(autoincrement())
name String?
teacherId Int?
teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id])
students User[] @relation("TeacherStudents")
followedBy User[] @relation("UserFollows")
following User[] @relation("UserFollows")
}
© . This site is unofficial and not affiliated with Prisma Data, Inc.