Reputation: 18536
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])
}
I would like to find a player with most wins. How would I do that with prisma
? If there is no prisma "native" way to do it, what is the most efficient way to do this with raw SQL?
The best I could think of is:
prisma.player.findMany({
include: {
game: {
where: {
isWin: true,
},
},
},
})
But it has huge downside that you need to filter and order results in Node manually, and also store all results in memory while doing so.
Upvotes: 1
Views: 209
Reputation: 7268
Using the groupBy
API you can find the player with the most wins using two queries.
You'l need to use the orderByAggregateGroup
preview feature and use Prisma version 2.21.0
or later.
Update your Prisma Schema as follows
generator client {
provider = "prisma-client-js"
previewFeatures = ["orderByAggregateGroup"]
}
// ... rest of schema
Use a groupBy
query to do the following:
playerId
field.game
records where isWin
is true.The combined query looks like this:
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;
I would suggest checking out the Group By section of the Aggregation, grouping, and summarizing article in the prisma docs, which explains how group by works and how to use it with filtering and ordering.
You can trivially find the player using a findUnique
query as you have the id
.
const mostWinningPlayer = await prisma.player.findUnique({
where: {
id: mostWinningPlayerId,
},
});
Optionally, if you want the first "n" most winning players, just put the appropriate number in the take
condition of the first groupBy
query. Then you can do a findMany
with the in operator to get all the player records. If you're not sure how to do this, feel free to ask and I'll clarify with sample code.
Upvotes: 3