查找具有按条件过滤的大多数关系的实体
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 - 按“字段及其关系模型字段”之间的条件过滤模型