iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0
Modern Web

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

Day24. 一些讓你看來很強的 ORM - prisma (Count & Distinct)

  • 分享至 

  • xImage
  •  

Count

prisma 中如果你要查詢資料的數量,可以使用 count() 返回數量,例如我們想查詢總共有多少 user

// 10
const userCount = await prisma.user.count()

或是在 relation 中想知道我們 user 總共有多少個 posts ,可以透過 findMany 然後使用 include 知道每個 user posts 的數量是多少

const usersWithCount = await prisma.user.findMany({
  include: {
    _count: {
      select: { posts: true },
    },
  },
})
{ id: 1, _count: { posts: 3 } },
{ id: 2, _count: { posts: 2 } },
{ id: 3, _count: { posts: 2 } },
{ id: 4, _count: { posts: 0 } },
{ id: 5, _count: { posts: 0 } }

或是使用 select return 每個 userposts 數量,同時其他欄位不顯示

const usersWithCount = await prisma.user.findMany({
  select: {
    _count: {
      select: { posts: true },
    },
  },
})
[
 { _count: { posts: 3 } },
  { _count: { posts: 9 } },
  { _count: { posts: 7 } }
]

甚至也可以 return 多個 relationcount

const usersWithCount = await prisma.user.findMany({
  select: {
    _count: {
      select: {
        posts: true,
        recipes: true,
      },
    },
  },
})
[{
  _count: {
    posts: 3,
    recipes: 9
  }
}]

_count 其實還可以加上 filter 條件,例如以下的 query 代表 userpost 中他的 titlehelloposts 數量有多少

await prisma.user.findMany({
  select: {
    id: true,
    _count: {
      select: {
        posts: { where: { title: 'Hello!' } },
      },
    },
  },
})

所以我們可以知道 userIdcm20lktb100004de0vs2ta7nl 他有一篇 post 剛好就叫做 Hello!

[
  { id: 'cm20lktb100004de0vs2ta7nl', _count: { posts: 1 } },
  { id: 'cm20lktb800054de0gbdn4lxl', _count: { posts: 0 } },
]

下面的例子就是找尋 userpost 中他的 commentsAlice 留言得數量是多少

await prisma.user.findMany({
  select: {
    _count: {
      select: {
        posts: {
          where: { comments: { some: { author: { is: { name: 'Alice' } } } } },
        },
      },
    },
  },
})

Count null

有的時候假如我的有些欄位他是 optional 的,想知道有資料的數量跟沒資料得數量有多少,這邊我們可以在 select 中對你要確定的欄位加上 true ,而這邊的範例就是要找尋有 age 資料的 data 數量使多少

const usersWithCount = await prismaClient.user.count({
    select: {
      _all: true,
      age: true
    }
  })

所以可以知道總共有 87userage 欄位,然後總共有100筆資料

{ _all: 100, age: 87 }

或是可以透過 where 去找到沒有 age 的資料數量

const usersWithCount = await prismaClient.user.count({
    where: {
      age: null
    }
  })

where filter userprofileViews 是大於100 的 user 有幾個

const userCount = await prisma.user.count({
  where: {
    profileViews: {
      gte: 100,
    },
  },
})

甚至也可以反過來判斷 post 有被特定的 user.id relation 的數量有多少

const postCount = await prisma.post.count({
  where: {
    userId: 29,
  },
})

Distinct

Distinct 可以幫我們塞選重複性的資料,通常會搭配 select 看出每個欄位使用過的 value 有哪些

 const namesList = await prismaClient.user.findMany({
    distinct: ['name'],
    select: {
      name: true
    }
  })

如此就知道目前的 name 用過哪些了

[
 { name: 'Carmen Kreiger' },
  { name: 'Rochelle Schuster' },
  { name: 'Frances Kuphal-Ankunding' }
]

Demo

有時候我們使用 count 來查詢,會有重述性資料的問題,例如以下的 model ,每個 user 他每一款完過的遊戲的分數紀錄可能會有很多個,但如果我們只想要知道這個 user 他每一款的遊戲,拿到的最多分是多少,就很適合用 Distinct 解決

model User {
  id   Int     @id @default(autoincrement())
  name String?
  play Play[]
}

model Game {
  id   Int     @id @default(autoincrement())
  name String?
  play Play[]
}

model Play {
  id       Int   @id @default(autoincrement())
  score    Int?  @default(0)
  playerId Int?
  player   User? @relation(fields: [playerId], references: [id])
  gameId   Int?
  game     Game? @relation(fields: [gameId], references: [id])
}

  • 先透過 orderBy 將分數排序
  • distinctgameId 以及 playerId中查看有哪些組合
  • select 選擇要看到哪些欄位
const distinctScores = await prisma.play.findMany({
  distinct: ['playerId', 'gameId'],
  orderBy: {
    score: 'desc',
  },
  select: {
    score: true,
    game: {
      select: {
        name: true,
      },
    },
    player: {
      select: {
        name: true,
      },
    },
  },
})
[
  {
    score: 900,
    game: { name: 'Pacman' },
    player: { name: 'Bert Bobberton' }
  },
  {
    score: 400,
    game: { name: 'Pacman' },
    player: { name: 'Nellie Bobberton' }
  }
]

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

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


上一篇
Day23. 一些讓你看來很強的 ORM - prisma ( Aggregate & Group by)
下一篇
Day25. 一些讓你看來很強的 ORM - prisma (TypeSQL)上
系列文
一些讓你看來很強的 ORM - prisma30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言