【问题标题】:Find entity with most relations filtered by criteria查找具有按条件过滤的大多数关系的实体
【发布时间】:2021-10-03 09:05:25
【问题描述】:
model Player {
  id   String @id
  name String @unique
  game Game[]
}

model Game {
  id       String   @id
  isWin    Boolean
  playerId String
  player   Player   @relation(fields: [playerId], references: [id])
}

我想找到获胜次数最多的玩家。我将如何使用prisma 做到这一点?如果没有 prisma “本机”方式来做到这一点,那么使用原始 SQL 执行此操作的最有效方式是什么?

我能想到的最好的是:

    prisma.player.findMany({
      include: {
        game: {
          where: {
            isWin: true,
          },
        },
      },
    })

但它有一个巨大的缺点,您需要在 Node 中手动过滤和排序结果,同时还要将所有结果存储在内存中。

【问题讨论】:

    标签: sql prisma


    【解决方案1】:

    使用groupBy API,您可以通过两个查询找到获胜次数最多的玩家。

    1.激活 orderByAggregateGroup

    您需要使用 orderByAggregateGroup 预览功能并使用 Prisma 版本 2.21.0 或更高版本。

    如下更新您的 Prisma 架构

    generator client {
      provider        = "prisma-client-js"
      previewFeatures = ["orderByAggregateGroup"]  
    }
    // ... rest of schema
    
    

    2.查找最多获胜玩家的 playerId

    使用groupBy 查询执行以下操作:

    1. playerId 字段分组游戏。
    2. 查找game 记录的计数,其中isWin 为真。
    3. 按 2 中提到的计数降序排列。
    4. 只取 1 个结果(因为我们想要获胜最多的玩家。您可以更改此设置以获取前 n 个玩家)。

    组合查询如下所示:

     const groupByResult = await prisma.game.groupBy({
            by: ["playerId"],
            where: {
                isWin: true,
            },
            _count: {
                isWin: true,
            },
            orderBy: {
                _count: {
                    isWin: "desc",
                },
            },
            take: 1,   // change to "n" you want to find the first-n most winning players. 
        });
    
        const mostWinningPlayerId = groupByResult[0].playerId;
    
    

    我建议查看 prisma 文档中 Aggregation, grouping, and summarizing article 的 Group By 部分,该部分解释了 group by 的工作原理以及如何将其用于过滤和排序。

    3.使用 findUnique 查询玩家数据

    您可以使用findUnique 查询轻松找到播放器,因为您有id

    const mostWinningPlayer = await prisma.player.findUnique({
            where: {
                id: mostWinningPlayerId,
            },
        });
    
    

    或者,如果您想要前“n”个最多获胜的玩家,只需在第一个groupBy 查询的take 条件中输入适当的数字。然后您可以使用in operator 执行findMany 以获取所有玩家记录。如果您不确定如何执行此操作,请随时询问,我将通过示例代码进行说明。

    【讨论】:

    • 其实groupBy也试过这种方法,但不知道orderByAggregateGroup标志,谢谢!我希望有一个查询解决方案,但我想这现在可行。
    • 欢迎您!我认为目前不支持单个查询解决方案。您可以order by the count of related records,但不能添加条件计数,例如,当isWin: true
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 2023-03-16
    • 2023-01-19
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多