iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
Modern Web

一些讓你看來很強的 ORM - prisma系列 第 14

Day14. 一些讓你看來很強的 ORM - prisma (Fluent API)

  • 分享至 

  • xImage
  •  

今天要來補充一下 relations queries 的內容~

Fluent API

Fluent API 他是一個可以讓你在 query data 的時候遍歷於不同的 table 之間,他可以改變你 query data 的方式外,同時也可以幫你自動優化 query 的效能,透過 function 的方式,讓你自己決定你現在要在哪個 table 顯示結果

以這邊的 user 為例子,我們想找到 emailalice@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 時,只透過一次 queriesgenerates data
  • 範例二 則是會 separate 兩個 database query 其目的是提升整體的 query 效能

因為在 prisma 中他會自動 batched queries 透過 prisma 底層的 dataloader gererateprisma 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)
  })

postWithCategories

{
  id: 2,
  title: 'title',
  categories: [
    {
      postId: 2,
      categoryId: 9,
      assignedAt: 2024-09-27T01:51:40.253Z,
      assignedBy: 'Danny'
    }
  ]
}

categoriesInPost

[
  {
    postId: 2,
    categoryId: 9,
    assignedAt: 2024-09-27T01:51:40.253Z,
    assignedBy: 'Danny'
  }
]

以上兩個 return 的資料結構雖然不一樣,但其實他們都是做一樣的事情,那就是找到特定的 posts 有哪些 categories ,就結果來看 postWithCategories 的結構因為是從 post modelquery data 的,prisma 預設沒有 return relation data 所以會需要 include ,導致最終的 data 會有 nest 狀況,但如果是 categoriesInPost 透過 Fluent API 方式,最終的結果就乾淨許多,畢竟我們只需要找到對應的 categories 而已~

最後補充一下 Fluent API 只能用在 query signalapi 上,例如 findUnique 等等,以確保在 chain 的過程中資料的唯一性。

// This query is illegal
const posts = await prisma.user.findMany().posts()

大家如果有問題可以來小弟的群組討論~

✅ 前端社群 :
https://lihi3.cc/kBe0Y


上一篇
Day13. 一些讓你看來很強的 ORM - prisma (relation)m-n
下一篇
Day15. 一些讓你看來很強的 ORM - prisma (Self Relation)
系列文
一些讓你看來很強的 ORM - prisma30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言