Tengo una relación explícita de muchos a muchos que se ve así
model Fighter { id Int @id @default(autoincrement()) name String image String? description String? battles Battle[] votes Vote[] } model Vote { id Int @id @default(autoincrement()) Fighter Fighter @relation(fields: [fighterId], references: [id]) fighterId Int Battle Battle @relation(fields: [battleId], references: [id]) battleId Int } model Battle { id Int @id @default(autoincrement()) slug String @unique name String fighters Fighter[] votes Vote[] }Un luchador tiene múltiples batallas, una batalla tiene múltiples luchadores y un voto pertenece a un luchador y una batalla. Quiero recuperar una batalla por slug con los luchadores asociados y contar todos los votos que pertenecen a cada luchador para esta batalla. Aquí está mi consulta para realizar eso:
await prisma.battle.findUnique({ where: { slug }, include: { fighters: { include: { _count: { select: { votes: true, } } } } } });Pero con esta consulta, el recuento de votos no está vinculado a la batalla, lo que significa que contará todos los votos del luchador y no tendrá en cuenta la batalla. Soy nuevo en prisma, así que creo que hay una manera de lograr lo que quiero, pero no puedo hacerlo.
Afaik, esto no es posible con la API _count . Esto es lo mejor que se me ocurre:
Método 1:
solo incluya votos y calcule el conteo después
const _battle = await prisma.battle.findUnique({ where: { slug }, include: { fighters: { include: { votes: { where: { Battle: { slug } }, }, }, }, }, }); const battle = { ..._battle, fighters: _battle?.fighters.map(({ votes, ...rest }) => ({ ...rest, _count: { votes: votes.length }, })), }; Método 2:
Obtén el conteo de votos usando groupBy y mapéalo con la consulta de batalla
const [votes, _battle] = await Promise.all([ prisma.vote.groupBy({ where: { Battle: { slug } }, by: ['fighterId'], _count: { _all: true }, }), prisma.battle.findUnique({ where: { slug }, include: { fighters: true, }, }), ]); const battle = { ..._battle, fighters: _battle?.fighters.map((fighter) => ({ ...fighter, _count: { votes: votes.find(({ fighterId }) => fighterId === fighter.id)?._count ._all, }, })), };Ambos métodos producirán una respuesta como esta:
"battle": { "id": 1, "slug": "A", "name": "A", "fighters": [ { "id": 1, "name": "F1", "image": null, "description": null, "_count": { "votes": 2 } }, { "id": 2, "name": "F2", "image": null, "description": null, "_count": { "votes": 1 } } ] }