Aggregazioni
Aggregazioni con Prisma
Prisma supporta operazioni di aggregazione direttamente nel client, senza dover scrivere SQL raw.
aggregate()
Il metodo aggregate() permette di calcolare valori aggregati su un modello.
_count
// Contare tutti gli utenti
const totalUsers = await prisma.user.count()
// Contare con filtri
const activeUsers = await prisma.user.count({
where: { isActive: true },
})
// Contare campi non-null specifici
const result = await prisma.user.aggregate({
_count: {
_all: true, // Totale record
email: true, // Record con email non-null
bio: true, // Record con bio non-null
},
})
// result._count._all => 100
// result._count.bio => 45
_sum, _avg, _min, _max
const orderStats = await prisma.order.aggregate({
_sum: {
total: true,
quantity: true,
},
_avg: {
total: true,
},
_min: {
total: true,
createdAt: true,
},
_max: {
total: true,
createdAt: true,
},
})
console.log('Totale vendite:', orderStats._sum.total)
console.log('Media ordine:', orderStats._avg.total)
console.log('Ordine minimo:', orderStats._min.total)
console.log('Ordine massimo:', orderStats._max.total)
console.log('Primo ordine:', orderStats._min.createdAt)
Aggregazioni con Filtri
// Statistiche solo per ordini completati dell'ultimo mese
const monthlyStats = await prisma.order.aggregate({
where: {
status: 'DELIVERED',
createdAt: {
gte: new Date('2026-01-01'),
},
},
_sum: { total: true },
_avg: { total: true },
_count: { _all: true },
})
groupBy()
Raggruppa i risultati per uno o piu’ campi e applica aggregazioni a ciascun gruppo.
Raggruppamento Base
// Contare utenti per ruolo
const usersByRole = await prisma.user.groupBy({
by: ['role'],
_count: {
_all: true,
},
})
// [
// { role: 'USER', _count: { _all: 80 } },
// { role: 'ADMIN', _count: { _all: 5 } },
// { role: 'MODERATOR', _count: { _all: 15 } },
// ]
Raggruppamento con Aggregazioni
// Vendite per categoria
const salesByCategory = await prisma.order.groupBy({
by: ['category'],
_sum: {
total: true,
},
_avg: {
total: true,
},
_count: {
_all: true,
},
orderBy: {
_sum: {
total: 'desc',
},
},
})
Raggruppamento Multiplo
// Raggruppare per citta' e ruolo
const groupedUsers = await prisma.user.groupBy({
by: ['city', 'role'],
_count: {
_all: true,
},
orderBy: {
_count: {
_all: 'desc',
},
},
})
having
Filtra i gruppi dopo l’aggregazione (equivalente SQL di HAVING):
// Citta' con piu' di 10 utenti
const popularCities = await prisma.user.groupBy({
by: ['city'],
_count: {
_all: true,
},
having: {
_all: {
_count: {
gt: 10,
},
},
},
})
// Categorie con vendite totali superiori a 1000
const topCategories = await prisma.order.groupBy({
by: ['category'],
_sum: {
total: true,
},
having: {
total: {
_sum: {
gt: 1000,
},
},
},
})
Filtri where e having Insieme
// where filtra PRIMA del raggruppamento
// having filtra DOPO il raggruppamento
const result = await prisma.order.groupBy({
by: ['category'],
where: {
status: 'DELIVERED', // Solo ordini consegnati
createdAt: { gte: new Date('2026-01-01') },
},
_sum: { total: true },
_count: { _all: true },
having: {
total: {
_sum: { gte: 500 }, // Solo categorie con totale >= 500
},
},
orderBy: {
_sum: { total: 'desc' },
},
})
Conteggio nelle Relazioni
Puoi includere il conteggio delle relazioni direttamente nelle query:
const usersWithCounts = await prisma.user.findMany({
include: {
_count: {
select: {
posts: true,
comments: true,
followers: true,
},
},
},
})
// Accedere ai conteggi
usersWithCounts.forEach((user) => {
console.log(`${user.name}: ${user._count.posts} post, ${user._count.comments} commenti`)
})
// Filtrare per conteggio di relazione
const prolificAuthors = await prisma.user.findMany({
where: {
posts: {
some: {},
},
},
include: {
_count: { select: { posts: true } },
},
orderBy: {
posts: { _count: 'desc' },
},
take: 10,
})