Aller au contenu

Regroupement et Agrégations

Archie Core offre des capacités puissantes de regroupement et d’agrégation via son API GraphQL. Vous pouvez regrouper les enregistrements par valeurs de champs, calculer des fonctions d’agrégation (COUNT, SUM, AVG, MIN, MAX, COUNT_DISTINCT), filtrer les groupes avec des conditions HAVING et trier les résultats par valeurs agrégées.

Lors de l’utilisation du regroupement et des agrégations, les arguments suivants sont disponibles sur toute requête de liste :

ArgumentTypeDescription
groupBy[{TableName}GroupBy]Champs pour regrouper les résultats
aggregateBy[{TableName}AggregateInput]Fonctions d’agrégation à calculer
having[{TableName}HavingFilterInput]Filtrer les groupes par résultats agrégés
aggregateSort[{TableName}AggregateSortInput]Trier les résultats par valeurs agrégées

Ces arguments peuvent être combinés avec des arguments standard comme filter, first, skip et orderBy.

L’argument groupBy accepte un tableau de valeurs enum représentant les champs par lesquels regrouper. Les valeurs enum suivent le modèle : le nom du champ en camelCase converti en MAJUSCULES.

Convention de nommage :

Nom de colonne (DB)Nom de champ (GraphQL)Valeur enum GroupBy
payment_methodpaymentMethodPAYMENTMETHOD
created_atcreatedAtCREATEDAT
statusstatusSTATUS
category_idcategoryIdCATEGORYID

Exemple : Regrouper les étudiants par statut actif

Section intitulée « Exemple : Regrouper les étudiants par statut actif »

Requête

query {
students(groupBy: [ISACTIVE]) {
items {
isActive
}
count
}
}

Réponse

{
"data": {
"students": {
"items": [
{ "isActive": true },
{ "isActive": false }
],
"count": 2
}
}
}

L’argument aggregateBy permet de calculer des fonctions d’agrégation sur des données regroupées (ou non). Chaque agrégat nécessite une function, un field optionnel et un alias obligatoire.

input {TableName}AggregateInput {
function: AggregateFunction!
field: {TableName}AggregateField
alias: String!
}
FonctionDescriptionfield requis ?
COUNTCompter les lignesNon (utilise COUNT(*) si omis)
SUMSomme des valeurs numériquesOui
AVGCalculer la moyenneOui
MINTrouver la valeur minimaleOui
MAXTrouver la valeur maximaleOui
COUNT_DISTINCTCompter les valeurs distinctesOui

L’enum field suit la même convention MAJUSCULES que GroupBy.

L’alias est une chaîne que vous choisissez pour nommer le résultat. Il apparaît comme clé dans l’objet de réponse aggregates.

Exemple : Compter et moyenner l’âge des étudiants groupés par statut actif

Section intitulée « Exemple : Compter et moyenner l’âge des étudiants groupés par statut actif »

Requête

query {
students(
groupBy: [ISACTIVE]
aggregateBy: [
{ function: COUNT, alias: "totalStudents" }
{ function: AVG, field: AGE, alias: "avgAge" }
]
) {
items {
isActive
}
count
aggregates
}
}

Réponse

{
"data": {
"students": {
"items": [
{ "isActive": true },
{ "isActive": false }
],
"count": 2,
"aggregates": [
{ "totalStudents": 5, "avgAge": 23.4 },
{ "totalStudents": 2, "avgAge": 21.0 }
]
}
}
}

Chaque entrée du tableau aggregates correspond au groupe au même index dans items.

L’argument having filtre les groupes en fonction des résultats agrégés, équivalent à la clause SQL HAVING. Il utilise un type d’entrée dédié avec trois champs.

input {TableName}HavingFilterInput {
alias: String!
operator: HavingOperator!
value: Float!
}
  • alias : Doit correspondre à un alias défini dans aggregateBy.
  • operator : L’opérateur de comparaison (voir tableau ci-dessous).
  • value : Le seuil numérique à comparer.
OpérateurÉquivalent SQL
EQUALS=
NOT_EQUALS!=
GREATER_THAN>
GREATER_THAN_OR_EQUAL>=
LESS_THAN<
LESS_THAN_OR_EQUAL<=

Requête

query {
students(
groupBy: [CITYID]
aggregateBy: [
{ function: COUNT, alias: "studentCount" }
]
having: [
{ alias: "studentCount", operator: GREATER_THAN, value: 3 }
]
) {
items {
cityId
}
count
aggregates
}
}

Réponse

{
"data": {
"students": {
"items": [
{ "cityId": "e14638cb-6d72-4a36-b30f-9b763136a7bb" }
],
"count": 1,
"aggregates": [
{ "studentCount": 5 }
]
}
}
}

Seuls les groupes satisfaisant la condition d’agrégation sont retournés.

L’argument aggregateSort trie les résultats groupés par une valeur agrégée, plutôt que par un champ régulier.

input {TableName}AggregateSortInput {
alias: String!
direction: SortDirection!
}
  • alias : Doit correspondre à un alias défini dans aggregateBy.
  • direction : ASC (ascendant) ou DESC (descendant).

Exemple : Top 3 des villes par nombre d’étudiants

Section intitulée « Exemple : Top 3 des villes par nombre d’étudiants »

Requête

query {
students(
groupBy: [CITYID]
aggregateBy: [
{ function: COUNT, alias: "studentCount" }
]
aggregateSort: [
{ alias: "studentCount", direction: DESC }
]
first: 3
) {
items {
cityId
}
count
aggregates
}
}

Réponse

{
"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 }
]
}
}
}

Vous pouvez combiner filter, groupBy, aggregateBy, having, aggregateSort et first dans une seule requête pour des analyses complexes.

Exemple : Top 5 des villes d’étudiants actifs avec âge moyen supérieur à 20, triées par âge moyen

Section intitulée « Exemple : Top 5 des villes d’étudiants actifs avec âge moyen supérieur à 20, triées par âge moyen »

Requête

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
}
}

Réponse

{
"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 }
]
}
}
}

Cette requête :

  1. Filtre uniquement les étudiants actifs (filter).
  2. Regroupe par ville (groupBy).
  3. Calcule le nombre, l’âge moyen et l’âge max pour chaque groupe (aggregateBy).
  4. Conserve uniquement les groupes avec âge moyen supérieur à 20 (having).
  5. Trie par âge moyen décroissant (aggregateSort).
  6. Limite aux 5 premiers groupes (first).

Lors de l’utilisation des agrégations, la réponse suit le type Connection standard avec un champ supplémentaire aggregates :

ChampTypeDescription
items[{TableName}!]!Les enregistrements groupés (un par groupe, contenant les valeurs des champs groupés)
countInt!Nombre de groupes retournés
pageInfoPageInfo!Info de pagination (hasNextPage, hasPreviousPage)
aggregatesJSONTableau d’objets, chacun contenant les valeurs agrégées calculées indexées par alias

Le tableau aggregates est parallèle à items — l’agrégat à l’index i correspond au groupe à l’index i dans items.

  • Les valeurs enum GroupBy et AggregateField utilisent les MAJUSCULES du nom du champ en camelCase : payment_methodpaymentMethodPAYMENTMETHOD.
  • Les alias having doivent correspondre à un alias défini dans aggregateBy. Si l’alias ne correspond pas, la condition having est ignorée.
  • Les alias aggregateSort doivent correspondre à un alias défini dans aggregateBy.
  • COUNT sans field utilise COUNT(*), comptant toutes les lignes du groupe.
  • Plusieurs conditions having peuvent être combinées — toutes doivent être satisfaites (logique AND).
  • Plusieurs entrées aggregateSort sont appliquées par ordre de priorité (la première est le tri principal).
  • Les arguments de pagination standard (first, skip, after, before) fonctionnent avec les résultats groupés.
  • L’argument filter est appliqué avant le regroupement (équivalent à SQL WHERE), tandis que having est appliqué après le regroupement (équivalent à SQL HAVING).