跳到主要內容

將隱式多對多關係轉換為顯式多對多關係

問題

多對多關係是關聯式資料庫的重要面向,允許一個表格中的多個記錄與另一個表格中的多個記錄相關聯。Prisma 提供了兩種方法來建模多對多關係:隱式顯式

使用者有時會遇到需要從模型之間的隱式多對多關係轉換為顯式多對多關係的情況。將隱式關係轉換為顯式關係可讓您更精確地控制關係,並儲存特定於關係的其他資料,例如時間戳記或任何其他欄位。本指南提供逐步說明,介紹如何進行轉換。

解決方案

這將引導您完成在 Prisma 中將隱式多對多關係轉換為顯式關係的過程

考慮這些模型,透過 postsauthor 欄位具有隱式多對多關係

model User {
id Int @id @default(autoincrement())
name String
posts Post[]
}

model Post {
id Int @id @default(autoincrement())
title String
authors User[]
}

在上述模型中,一個 User 可以有多個貼文,而一個 Post 可以有多個作者。

若要將隱式關係轉換為顯式關係,我們需要建立關係表。關係表將包含參考多對多關係中涉及的兩個表格的外鍵。在我們的範例中,我們將建立一個名為 UserPost 的新模型。我們更新後的 schema.prisma 檔案會如下所示

model User {
id Int @id @default(autoincrement())
name String
posts Post[]
userPosts UserPost[]
}

model Post {
id Int @id @default(autoincrement())
title String
authors User[]
userPosts UserPost[]
}

model UserPost {
id Int @id @default(autoincrement())
userId Int
postId Int
user User @relation(fields: [userId], references: [id])
post Post @relation(fields: [postId], references: [id])
createdAt DateTime @default(now())

@@unique([userId, postId])
}

如果您使用 Prisma Migrate,則可以調用此命令

npx prisma migrate dev --name "added explicit relation"

遷移將建立 UserPost 表格,並建立 UserPost 模型與 UserPost 模型的一對多關係。

將現有資料從隱式關係表遷移到新建立的關係表

若要將現有資料從隱式關係表遷移到新的顯式關係表,您需要撰寫自訂遷移腳本。您可以使用 Prisma Client 與資料庫互動、從隱式關係表讀取資料,並將其寫入新的關係表。

考慮上述 UserPost 模型,以下是您可以使用的範例腳本來遷移資料。

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

// A `main` function so that you can use async/await
async function main() {
try {
// Fetch all users with their related posts
const users = await prisma.user.findMany({
include: { posts: true },
});

// Iterate over users and their posts, then insert records into the UserPost table
for (const user of users) {
for (const post of user.posts) {
await prisma.userPost.create({
data: {
userId: user.id,
postId: post.id,
},
});
}
}

console.log("Data migration completed.");
} catch (e) {
console.error(e);
}
}

main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});

一旦資料遷移到關係表,您就可以移除隱式關係欄位 (User 模型中的 postsPost 模型中的 author),如下所示

model User {
id Int @id @default(autoincrement())
name String
posts Post[]
userPosts UserPost[]
}

model Post {
id Int @id @default(autoincrement())
title String
authors User[]
userPosts UserPost[]
}

在架構檔案中進行變更後,您可以調用此命令

npx prisma migrate dev --name "removed implicit relation"

執行上述命令將會刪除隱式表格 _PostToUser

您現在已成功在 Prisma 中將隱式多對多關係轉換為顯式關係。