今天要來補充一下 relations queries 的內容~
Fluent API 他是一個可以讓你在 query data 的時候遍歷於不同的 table 之間,他可以改變你 query data 的方式外,同時也可以幫你自動優化 query 的效能,透過 function 的方式,讓你自己決定你現在要在哪個 table 顯示結果
以這邊的 user 為例子,我們想找到 email 是 alice@prisma.io 做的 post ,我們會在 post model 中透過 findMany 方式去找尋。
// 範例一
const postsByUser = await prisma.post.findMany({
where: {
author: {
email: 'alice@prisma.io',
},
},
})
但如果是 Fluent API 寫法可以直接反過來使用,只要在最後 return posts function 就好
// 範例二
const postsByUser: Post[] = await prisma.user
.findUnique({ where: { email: 'alice@prisma.io' } })
.posts()
兩者最大的區別會是:
範例一 在 query data 時,只透過一次 queries 去 generates data
範例二 則是會 separate 兩個 database query 其目的是提升整體的 query 效能因為在 prisma 中他會自動 batched queries 透過 prisma 底層的 dataloader gererate 到 prisma client,同時解決 ORM 中常發現的 n + 1 的問題,如果讀者不知道什麼是 n + 1 的話可以看小弟的 文章~
Note: You can use the fact that .findUnique({ where: { email: 'alice@prisma.io' } }).posts() queries are automatically batched by the Prisma dataloader in Prisma Client to avoid the n+1 problem in GraphQL resolvers.
以我們昨天的 model 為例子,同樣只透過 post id 去找到對應的 categories
const categoriesOfPost: Category[] = await prisma.post
.findUnique({ where: { id: 1 } })
.categories()
而且 Fluent API 採用 chain function 的方式,所以你可以不停的遍歷不同 model 之間
const posts: Post[] = await prisma.profile
.findUnique({ where: { id: 1 } })
.user()
.posts()
最後我們根據昨天的 demo 比較一下使用 Fluent API return 的差異吧~
const getCategoriesOfPost = async () => {
const postWithCategories = await prismaClient.post.findUnique({
where: {
id: 2,
title: 'title'
},
include: {
categories: true
}
})
const categoriesInPost = await prismaClient.post.findUnique({
where: {
id: 2,
title: 'title'
}
}).categories()
console.dir({
categoriesInPost,
postWithCategories
}, {
depth: 3
})
}
getCategoriesOfPost()
.then(async () => {
await prismaClient.$disconnect()
})
.catch(async e => {
await prismaClient.$disconnect()
process.exit(1)
})
{
id: 2,
title: 'title',
categories: [
{
postId: 2,
categoryId: 9,
assignedAt: 2024-09-27T01:51:40.253Z,
assignedBy: 'Danny'
}
]
}
[
{
postId: 2,
categoryId: 9,
assignedAt: 2024-09-27T01:51:40.253Z,
assignedBy: 'Danny'
}
]
以上兩個 return 的資料結構雖然不一樣,但其實他們都是做一樣的事情,那就是找到特定的 posts 有哪些 categories ,就結果來看 postWithCategories 的結構因為是從 post model 去 query data 的,prisma 預設沒有 return relation data 所以會需要 include ,導致最終的 data 會有 nest 狀況,但如果是 categoriesInPost 透過 Fluent API 方式,最終的結果就乾淨許多,畢竟我們只需要找到對應的 categories 而已~
最後補充一下 Fluent API 只能用在 query signal 的 api 上,例如 findUnique 等等,以確保在 chain 的過程中資料的唯一性。
// This query is illegal
const posts = await prisma.user.findMany().posts()
✅ 前端社群 :
https://lihi3.cc/kBe0Y