Saltar al contenido principal

Agregación

[Traducción Beta No Oficial]

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Agregación

La opción Aggregate permite añadir una o más funciones de agregación.

package main

import (
"context"

"<project>/ent"
"<project>/ent/payment"
"<project>/ent/pet"
)

func Do(ctx context.Context, client *ent.Client) {
// Aggregate one field.
sum, err := client.Payment.Query().
Aggregate(
ent.Sum(payment.Amount),
).
Int(ctx)

// Aggregate multiple fields.
var v []struct {
Sum, Min, Max, Count int
}
err := client.Pet.Query().
Aggregate(
ent.Sum(pet.FieldAge),
ent.Min(pet.FieldAge),
ent.Max(pet.FieldAge),
ent.Count(),
).
Scan(ctx, &v)
}

Agrupación por campos

Agrupa por los campos name y age de todos los usuarios y suma su edad total.

package main

import (
"context"

"<project>/ent"
"<project>/ent/user"
)

func Do(ctx context.Context, client *ent.Client) {
var v []struct {
Name string `json:"name"`
Age int `json:"age"`
Sum int `json:"sum"`
Count int `json:"count"`
}
err := client.User.Query().
GroupBy(user.FieldName, user.FieldAge).
Aggregate(ent.Count(), ent.Sum(user.FieldAge)).
Scan(ctx, &v)
}

Agrupación por un solo campo.

package main

import (
"context"

"<project>/ent"
"<project>/ent/user"
)

func Do(ctx context.Context, client *ent.Client) {
names, err := client.User.
Query().
GroupBy(user.FieldName).
Strings(ctx)
}

Agrupación por relaciones (edges)

Las funciones de agregación personalizadas pueden ser útiles para implementar lógica específica de almacenamiento.

Este ejemplo muestra cómo agrupar por el id y el name de todos los usuarios, calculando la media de age de sus mascotas.

package main

import (
"context"
"log"

"<project>/ent"
"<project>/ent/pet"
"<project>/ent/user"
)

func Do(ctx context.Context, client *ent.Client) {
var users []struct {
ID int
Name string
Average float64
}
err := client.User.Query().
GroupBy(user.FieldID, user.FieldName).
Aggregate(func(s *sql.Selector) string {
t := sql.Table(pet.Table)
s.Join(t).On(s.C(user.FieldID), t.C(pet.OwnerColumn))
return sql.As(sql.Avg(t.C(pet.FieldAge)), "average")
}).
Scan(ctx, &users)
}

Having + Agrupación

Los modificadores SQL personalizados son útiles para controlar todas las partes de la consulta. A continuación se muestra cómo recuperar los usuarios de mayor edad para cada rol.

package main

import (
"context"
"log"

"entgo.io/ent/dialect/sql"
"<project>/ent"
"<project>/ent/user"
)

func Do(ctx context.Context, client *ent.Client) {
var users []struct {
Id Int
Age Int
Role string
}
err := client.User.Query().
Modify(func(s *sql.Selector) {
s.GroupBy(user.Role)
s.Having(
sql.EQ(
user.FieldAge,
sql.Raw(sql.Max(user.FieldAge)),
),
)
}).
ScanX(ctx, &users)
}

Nota: La inclusión de sql.Raw es crucial, ya que indica al predicado que sql.Max no es un argumento.

El código anterior genera esencialmente la siguiente consulta SQL:

SELECT * FROM user GROUP BY user.role HAVING user.age = MAX(user.age)