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 為例子,我們想找到 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)
  })

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 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


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

尚未有邦友留言

立即登入留言