將隱式多對多關係轉換為顯式多對多關係
問題
多對多關係是關係資料庫的重要組成部分,它允許一個表中的多個記錄與另一個表中的多個記錄相關聯。Prisma 提供了兩種建模多對多關係的方法:隱式和顯式。
使用者有時會遇到需要將模型間的隱式多對多關係轉換為顯式多對多關係的情況。將隱式關係轉換為顯式關係可以讓你對關係有更多的控制權,並存儲與該關係相關的額外資料,例如時間戳或任何其他欄位。本指南提供瞭如何進行此轉換的逐步說明。
解決方案
本文將指導你完成在 Prisma 中將隱式多對多關係轉換為顯式多對多關係的過程。
考慮這些透過 posts 和 author 欄位具有隱式多對多關係的模型。
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 表,並建立 User 和 Post 模型與 UserPost 模型之間的一對多關係。
將現有資料從隱式關係表遷移到新建立的關係表
要將現有資料從隱式關係表遷移到新的顯式關係表,你需要編寫一個自定義遷移指令碼。你可以使用 Prisma Client 與資料庫互動,從隱式關係表讀取資料,並將其寫入新的關係表。
考慮到上述 User 和 Post 模型,這裡有一個你可以用來遷移資料的示例指令碼。
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 模型中的 posts 和 Post 模型中的 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[]
}
在 schema 檔案中進行更改後,你可以呼叫此命令:
npx prisma migrate dev --name "removed implicit relation"
執行上述命令將刪除隱式表 _PostToUser。
你現在已成功將 Prisma 中的隱式多對多關係轉換為顯式多對多關係。