查找具有按条件过滤的大多数关系的实体

Posted

技术标签:

【中文标题】查找具有按条件过滤的大多数关系的实体【英文标题】: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 中手动过滤和排序结果,同时还要将所有结果存储在内存中。

【问题讨论】:

【参考方案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 查询执行以下操作:

    playerId 字段分组游戏。 查找game 记录的计数,其中isWin 为真。 按 2 中提到的计数降序排列。 只取 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

以上是关于查找具有按条件过滤的大多数关系的实体的主要内容,如果未能解决你的问题,请参考以下文章

在实体框架中加载具有过滤条件的子对象记录

Laravel - 按“字段及其关系模型字段”之间的条件过滤模型

具有特定条件计数的 Mongodb 聚合并按输出投影的日期范围过滤不能按预期工作

按条件过滤大熊猫

NSPredicate 按属性过滤核心数据关系 NSSet

如何按不相关的实体过滤核心数据