Agrupación y Agregaciones
Archie Core ofrece potentes capacidades de agrupación y agregación a través de su API GraphQL. Puedes agrupar registros por valores de campos, calcular funciones de agregación (COUNT, SUM, AVG, MIN, MAX, COUNT_DISTINCT), filtrar grupos con condiciones HAVING y ordenar resultados por valores agregados.
Argumentos de consulta
Sección titulada «Argumentos de consulta»Al usar agrupación y agregaciones, los siguientes argumentos están disponibles en cualquier consulta de lista:
| Argumento | Tipo | Descripción |
|---|---|---|
groupBy | [{TableName}GroupBy] | Campos por los que agrupar resultados |
aggregateBy | [{TableName}AggregateInput] | Funciones de agregación a calcular |
having | [{TableName}HavingFilterInput] | Filtrar grupos por resultados agregados |
aggregateSort | [{TableName}AggregateSortInput] | Ordenar resultados por valores agregados |
Estos argumentos pueden combinarse con argumentos estándar como filter, first, skip y orderBy.
GroupBy
Sección titulada «GroupBy»El argumento groupBy acepta un array de valores enum que representan los campos por los que agrupar. Los valores enum siguen el patrón: el nombre del campo en camelCase convertido a MAYÚSCULAS.
Convención de nombres:
| Nombre de columna (DB) | Nombre de campo (GraphQL) | Valor enum GroupBy |
|---|---|---|
payment_method | paymentMethod | PAYMENTMETHOD |
created_at | createdAt | CREATEDAT |
status | status | STATUS |
category_id | categoryId | CATEGORYID |
Ejemplo: Agrupar estudiantes por estado activo
Sección titulada «Ejemplo: Agrupar estudiantes por estado activo»Solicitud
query { students(groupBy: [ISACTIVE]) { items { isActive } count }}Respuesta
{ "data": { "students": { "items": [ { "isActive": true }, { "isActive": false } ], "count": 2 } }}AggregateBy
Sección titulada «AggregateBy»El argumento aggregateBy permite calcular funciones de agregación sobre datos agrupados (o no agrupados). Cada agregado requiere una function, un field opcional y un alias obligatorio.
Estructura AggregateInput
Sección titulada «Estructura AggregateInput»input {TableName}AggregateInput { function: AggregateFunction! field: {TableName}AggregateField alias: String!}Funciones de agregación disponibles
Sección titulada «Funciones de agregación disponibles»| Función | Descripción | ¿field requerido? |
|---|---|---|
COUNT | Contar filas | No (usa COUNT(*) cuando se omite) |
SUM | Sumar valores numéricos | Sí |
AVG | Calcular promedio | Sí |
MIN | Encontrar valor mínimo | Sí |
MAX | Encontrar valor máximo | Sí |
COUNT_DISTINCT | Contar valores distintos | Sí |
El enum field sigue la misma convención MAYÚSCULAS que GroupBy.
El alias es una cadena que eliges para nombrar el resultado. Aparece como clave en el objeto de respuesta aggregates.
Ejemplo: Contar y promediar edad de estudiantes agrupados por estado activo
Sección titulada «Ejemplo: Contar y promediar edad de estudiantes agrupados por estado activo»Solicitud
query { students( groupBy: [ISACTIVE] aggregateBy: [ { function: COUNT, alias: "totalStudents" } { function: AVG, field: AGE, alias: "avgAge" } ] ) { items { isActive } count aggregates }}Respuesta
{ "data": { "students": { "items": [ { "isActive": true }, { "isActive": false } ], "count": 2, "aggregates": [ { "totalStudents": 5, "avgAge": 23.4 }, { "totalStudents": 2, "avgAge": 21.0 } ] } }}Cada entrada en el array aggregates corresponde al grupo en el mismo índice en items.
El argumento having filtra grupos según los resultados agregados, equivalente a la cláusula SQL HAVING. Utiliza un tipo de entrada dedicado con tres campos.
Estructura HavingFilterInput
Sección titulada «Estructura HavingFilterInput»input {TableName}HavingFilterInput { alias: String! operator: HavingOperator! value: Float!}alias: Debe coincidir con un alias definido enaggregateBy.operator: El operador de comparación (ver tabla abajo).value: El umbral numérico contra el que comparar.
Operadores disponibles
Sección titulada «Operadores disponibles»| Operador | Equivalente SQL |
|---|---|
EQUALS | = |
NOT_EQUALS | != |
GREATER_THAN | > |
GREATER_THAN_OR_EQUAL | >= |
LESS_THAN | < |
LESS_THAN_OR_EQUAL | <= |
Ejemplo: Ciudades con más de 3 estudiantes
Sección titulada «Ejemplo: Ciudades con más de 3 estudiantes»Solicitud
query { students( groupBy: [CITYID] aggregateBy: [ { function: COUNT, alias: "studentCount" } ] having: [ { alias: "studentCount", operator: GREATER_THAN, value: 3 } ] ) { items { cityId } count aggregates }}Respuesta
{ "data": { "students": { "items": [ { "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" } ], "count": 1, "aggregates": [ { "studentCount": 5 } ] } }}Solo se devuelven los grupos que cumplen la condición de agregación.
AggregateSort
Sección titulada «AggregateSort»El argumento aggregateSort ordena los resultados agrupados por un valor agregado, en lugar de por un campo regular.
Estructura AggregateSortInput
Sección titulada «Estructura AggregateSortInput»input {TableName}AggregateSortInput { alias: String! direction: SortDirection!}alias: Debe coincidir con un alias definido enaggregateBy.direction:ASC(ascendente) oDESC(descendente).
Ejemplo: Top 3 ciudades por número de estudiantes
Sección titulada «Ejemplo: Top 3 ciudades por número de estudiantes»Solicitud
query { students( groupBy: [CITYID] aggregateBy: [ { function: COUNT, alias: "studentCount" } ] aggregateSort: [ { alias: "studentCount", direction: DESC } ] first: 3 ) { items { cityId } count aggregates }}Respuesta
{ "data": { "students": { "items": [ { "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" }, { "cityId": "0174dc55-d494-4ebc-a0e9-13575461cad4" }, { "cityId": "a2b3c4d5-e6f7-8901-2345-678901234567" } ], "count": 3, "aggregates": [ { "studentCount": 5 }, { "studentCount": 3 }, { "studentCount": 2 } ] } }}Combinar todas las funciones
Sección titulada «Combinar todas las funciones»Puedes combinar filter, groupBy, aggregateBy, having, aggregateSort y first en una sola consulta para análisis complejos.
Ejemplo: Top 5 ciudades de estudiantes activos con edad promedio superior a 20, ordenadas por edad promedio
Sección titulada «Ejemplo: Top 5 ciudades de estudiantes activos con edad promedio superior a 20, ordenadas por edad promedio»Solicitud
query { students( filter: { isActive: { equals: true } } groupBy: [CITYID] aggregateBy: [ { function: COUNT, alias: "studentCount" } { function: AVG, field: AGE, alias: "avgAge" } { function: MAX, field: AGE, alias: "maxAge" } ] having: [ { alias: "avgAge", operator: GREATER_THAN, value: 20 } ] aggregateSort: [ { alias: "avgAge", direction: DESC } ] first: 5 ) { items { cityId } count aggregates }}Respuesta
{ "data": { "students": { "items": [ { "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" }, { "cityId": "0174dc55-d494-4ebc-a0e9-13575461cad4" } ], "count": 2, "aggregates": [ { "studentCount": 3, "avgAge": 24.3, "maxAge": 28 }, { "studentCount": 2, "avgAge": 22.5, "maxAge": 25 } ] } }}Esta consulta:
- Filtra solo estudiantes activos (
filter). - Agrupa por ciudad (
groupBy). - Calcula conteo, edad promedio y edad máxima en cada grupo (
aggregateBy). - Mantiene solo grupos con edad promedio superior a 20 (
having). - Ordena por edad promedio descendente (
aggregateSort). - Limita a los 5 grupos principales (
first).
Estructura de respuesta
Sección titulada «Estructura de respuesta»Al usar agregaciones, la respuesta sigue el tipo Connection estándar con un campo adicional aggregates:
| Campo | Tipo | Descripción |
|---|---|---|
items | [{TableName}!]! | Los registros agrupados (uno por grupo, con los valores de los campos agrupados) |
count | Int! | Número de grupos devueltos |
pageInfo | PageInfo! | Info de paginación (hasNextPage, hasPreviousPage) |
aggregates | JSON | Array de objetos, cada uno con los valores agregados calculados indexados por alias |
El array aggregates es paralelo a items — el agregado en el índice i corresponde al grupo en el índice i en items.
Notas importantes
Sección titulada «Notas importantes»- Los valores enum GroupBy y AggregateField usan MAYÚSCULAS del nombre del campo en camelCase:
payment_method→paymentMethod→PAYMENTMETHOD. - Los alias de having deben coincidir con un alias definido en
aggregateBy. Si no coinciden, la condición having se ignora. - Los alias de aggregateSort deben coincidir con un alias definido en
aggregateBy. - COUNT sin field usa
COUNT(*), contando todas las filas del grupo. - Múltiples condiciones having pueden combinarse — todas deben cumplirse (lógica AND).
- Múltiples entradas aggregateSort se aplican en orden de prioridad (la primera es el orden principal).
- Los argumentos de paginación estándar (
first,skip,after,before) funcionan con resultados agrupados. - El argumento filter se aplica antes de agrupar (equivalente a SQL WHERE), mientras que having se aplica después de agrupar (equivalente a SQL HAVING).