今天要來補充一下 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