Une requête d'agrégation traite les données de plusieurs entités indexées pour renvoyer une seule valeur récapitulative. Firestore en mode Datastore accepte les requêtes d'agrégation suivantes :
count()
sum()
avg()
Les requêtes d'agrégation simplifient le code de votre application et coûtent moins cher que l'extraction de chaque entité pour le traitement. Consultez cette page pour découvrir comment utiliser les requêtes d'agrégation.
Agrégation count()
Utilisez l'agrégation count()
pour renvoyer le nombre total d'entités indexées correspondant à une requête donnée. Par exemple, cette agrégation count()
renvoie le nombre total d'entités d'un type.
Java
Python
Go
aggregationCountQuery := datastore.NewQuery("Task"). NewAggregationQuery(). WithCount("total_tasks") countResults, err := client.RunAggregationQuery(ctx, aggregationCountQuery) count := countResults["total_tasks"] countValue := count.(*datastorepb.Value) fmt.Printf("Number of results from query: %d\n", countValue.GetIntegerValue())
GQL
AGGREGATE COUNT(*) AS total OVER ( SELECT * AS total FROM tasks )
GQL accepte une forme simplifiée des requêtes count()
:
SELECT COUNT(*) AS total FROM tasks
Cet exemple utilise un alias facultatif de total
.
La forme simplifiée n'est compatible qu'avec les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence sur GQL.
L'agrégation count()
tient compte de tous les filtres de la requête et de toutes les clauses limit
. Par exemple, l'agrégation suivante renvoie le nombre d'entités correspondant aux filtres spécifiés.
Java
Python
Go
aggregationCountQuery := datastore.NewQuery("Task"). FilterField("done", "=", true). NewAggregationQuery(). WithCount("total_tasks_done") countResults, err := client.RunAggregationQuery(ctx, aggregationCountQuery) count := countResults["total_tasks_done"] countValue := count.(*datastorepb.Value) fmt.Printf("Number of results from query: %d\n", countValue.GetIntegerValue())
GQL
AGGREGATE COUNT(*) OVER ( SELECT * FROM tasks WHERE is_done = false AND tag = 'house')
GQL accepte une forme simplifiée des requêtes count()
:
SELECT COUNT(*) AS total FROM tasks WHERE is_done = false AND tag = 'house'
Cet exemple utilise un alias facultatif de total
.
La forme simplifiée n'est compatible qu'avec les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence sur GQL.
Cet exemple montre comment compter jusqu'à une certaine valeur. Vous pouvez l'utiliser, par exemple, pour arrêter le décompte à un certain nombre et informer les utilisateurs qu'ils ont dépassé ce nombre.
Java
Python
Go
aggregationCountQuery := datastore.NewQuery("Task"). Limit(2). NewAggregationQuery(). WithCount("at_least") countResults, err := client.RunAggregationQuery(ctx, aggregationCountQuery) count := countResults["at_least"] countValue := count.(*datastorepb.Value) fmt.Printf("We have at least %d tasks\n", countValue.GetIntegerValue())
GQL
AGGREGATE COUNT_UP_TO(1000) OVER ( SELECT * FROM tasks WHERE is_done = false)
GQL accepte une forme simplifiée des requêtes count_up_to()
:
SELECT COUNT_UP_TO(1000) AS total FROM tasks WHERE is_done = false AND tag = 'house'
Cet exemple utilise un alias facultatif de total
.
La forme simplifiée n'est compatible qu'avec les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence sur GQL.
Agrégation sum()
Utilisez l'agrégation sum()
pour renvoyer la somme totale des valeurs numériques correspondant à une requête donnée. Par exemple, l'agrégation sum()
suivante renvoie la somme totale des valeurs numériques de la propriété donnée à partir des entités du type donné :
Java
Python
Go
aggregationSumQuery := datastore.NewQuery("Task"). NewAggregationQuery(). WithSum("hours", "total_hours") sumResults, err := client.RunAggregationQuery(ctx, aggregationSumQuery) sum := sumResults["total_hours"] sumValue := sum.(*datastorepb.Value) fmt.Printf("Sum of results from query: %d\n", sumValue.GetIntegerValue())
GQL
AGGREGATE SUM(hours) AS total_hours OVER ( SELECT * FROM tasks )
GQL accepte une forme simplifiée des requêtes sum()
:
SELECT SUM(hours) AS total_hours FROM tasks
Cet exemple utilise un alias facultatif de total_hours
.
La forme simplifiée n'est compatible qu'avec les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence sur GQL.
L'agrégation sum()
tient compte de tous les filtres de la requête et de toutes les clauses limit
. Par exemple, l'agrégation suivante renvoie une somme de la propriété spécifiée avec une valeur numérique dans les entités qui correspondent aux filtres donnés.
Java
Python
Cette requête nécessite un index tel que :
- kind: Task properties: - name: done - name: hours
Go
aggregationSumQuery := datastore.NewQuery("Task"). FilterField("done", "=", false). FilterField("tag", "=", "house"). NewAggregationQuery(). WithSum("hours", "total_hours") sumResults, err := client.RunAggregationQuery(ctx, aggregationSumQuery) sum := sumResults["total_hours"] sumValue := sum.(*datastorepb.Value) fmt.Printf("Sum of results from query: %d\n", sumValue.GetIntegerValue())
GQL
AGGREGATE SUM(hours) AS total_hours OVER ( SELECT * FROM tasks WHERE is_done = false AND tag = 'house' )
GQL accepte une forme simplifiée des requêtes sum()
:
SELECT SUM(hours) AS total_hours FROM tasks WHERE is_done = false AND tag = 'house'
Cet exemple utilise un alias facultatif de total_hours
.
La forme simplifiée n'est compatible qu'avec les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence sur GQL.
Agrégation avg()
Utilisez l'agrégation avg()
pour renvoyer la moyenne des valeurs numériques correspondant à une requête donnée. Par exemple, l'agrégation avg()
suivante renvoie la moyenne arithmétique de la propriété spécifiée à partir des valeurs de propriété numériques des entités qui correspondent à la requête :
Java
Python
Go
aggregationAvgQuery := datastore.NewQuery("Task"). NewAggregationQuery(). WithAvg("hours", "avg_hours") avgResults, err := client.RunAggregationQuery(ctx, aggregationAvgQuery) avg := avgResults["avg_hours"] avgValue := avg.(*datastorepb.Value) fmt.Printf("average hours: %f\n", avgValue.GetDoubleValue())
GQL
AGGREGATE AVG(hours) as avg_hours OVER ( SELECT * FROM tasks )
GQL accepte une forme simplifiée des requêtes avg()
:
SELECT AVG(hours) as avg_hours
Cet exemple utilise un alias facultatif de avg_hours
.
La forme simplifiée n'est compatible qu'avec les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence sur GQL.
L'agrégation avg()
tient compte de tous les filtres de la requête et de toutes les clauses limit
. Par exemple, l'agrégation suivante renvoie la moyenne arithmétique de la propriété spécifiée à partir des valeurs de propriété numériques des entités qui correspondent aux filtres de requête.
Java
Python
Cette requête nécessite un index tel que :
- kind: Task properties: - name: done - name: hours
Go
aggregationAvgQuery := datastore.NewQuery("Task"). FilterField("done", "=", false). FilterField("tag", "=", "house"). NewAggregationQuery(). WithAvg("hours", "avg_hours") avgResults, err := client.RunAggregationQuery(ctx, aggregationAvgQuery) avg := avgResults["avg_hours"] avgValue := avg.(*datastorepb.Value) fmt.Printf("average hours: %f\n", avgValue.GetDoubleValue())
GQL
AGGREGATE AVG(hours) as avg_hours OVER ( SELECT * FROM tasks WHERE is_done = false AND tag = 'house' )
GQL accepte une forme simplifiée des requêtes avg()
:
SELECT AVG(hours) as avg_hours FROM tasks WHERE is_done = false AND tag = 'house'
Cet exemple utilise un alias facultatif de avg_hours
.
La forme simplifiée n'est compatible qu'avec les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence sur GQL.
Calculer plusieurs agrégations dans une requête
Vous pouvez combiner plusieurs agrégations dans un même pipeline d'agrégation. Cela peut réduire le nombre de lectures d'index requises. Si la requête inclut des agrégations sur plusieurs champs, elle nécessite un index composite. De plus, chaque calcul d'agrégation n'inclut que les entités contenant tous les champs utilisés par chaque agrégation.
L'exemple suivant effectue plusieurs agrégations dans une même requête d'agrégation :
Java
Python
Go
aggregationQuery := datastore.NewQuery("Task"). NewAggregationQuery(). WithCount("total_tasks"). WithSum("hours", "total_hours"). WithAvg("hours", "avg_hours") Results, err := client.RunAggregationQuery(ctx, aggregationQuery) fmt.Printf("Number of results from query: %d\n", Results["total_tasks"].(*datastorepb.Value).GetIntegerValue()) fmt.Printf("Sum of results from query: %d\n", Results["total_hours"].(*datastorepb.Value).GetIntegerValue()) fmt.Printf("Avg of results from query: %f\n", Results["avg_hours"].(*datastorepb.Value).GetDoubleValue())
GQL
AGGREGATE SUM(hours) AS total_hours, COUNT(*) AS total_tasks OVER ( SELECT * FROM tasks WHERE is_done = false AND tag = 'house' )
GQL est compatible avec une forme simplifiée pour les requêtes d'agrégation :
SELECT SUM(hours) AS total_hours, COUNT(*) AS total_tasks FROM tasks WHERE is_done = false AND tag = 'house'
Cet exemple utilise les alias facultatifs total_hours
et total_tasks
.
La forme simplifiée n'est compatible qu'avec les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence sur GQL.
Les requêtes avec plusieurs agrégations n'incluent que les entités qui contiennent toutes les propriétés de chaque agrégation. Cela peut entraîner des résultats différents de ceux obtenus en effectuant chaque agrégation séparément.
Comportement et limites
Lorsque vous utilisez des requêtes d'agrégation, tenez compte des comportements et des limites suivants :
- La requête que vous fournissez à l'agrégation doit respecter les restrictions au niveau des requêtes.
Si une requête d'agrégation ne peut pas être résolue dans les 60 secondes, elle renvoie une erreur
DEADLINE_EXCEEDED
. Les performances dépendent de la configuration de votre index et de la taille de l'ensemble de données.Si l'opération ne peut pas être effectuée dans le délai de 60 secondes, une solution possible consiste à utiliser des curseurs pour fusionner plusieurs agrégations.
Les requêtes d'agrégation lisent les entrées d'index et n'incluent que les propriétés indexées dans le calcul.
L'ajout d'une clause
OrderBy
à la requête limite l'agrégation aux entités pour lesquelles la propriété de tri existe.Dans GQL, la forme simplifiée n'est pas compatible avec les clauses
ORDER BY
,LIMIT
niOFFSET
.Dans une requête de projection, vous ne pouvez agréger les données que des propriétés de la projection. Par exemple, dans la requête GQL
SELECT a, b FROM k WHERE c = 1
, vous ne pouvez agréger les données que parmia
oub
.Une agrégation
count()
ne supprime pas les doublons d'entités avec des propriétés de tableau. Chaque valeur de tableau correspondant à la requête ajoute un au nombre.Pour les agrégations
sum()
etavg()
, les valeurs non numériques sont ignorées. Les agrégationssum()
etavg()
ne prennent en compte que les valeurs entières, les valeurs numériques à virgule flottante et les codes temporels. Les codes temporels sont convertis en valeurs entières en microsecondes poursum()
,avg()
et les projections.Lorsque vous combinez plusieurs agrégations dans une même requête, notez que
sum()
etavg()
ignorent les valeurs non numériques, tandis quecount()
les inclut.Si vous combinez des agrégations qui se trouvent dans différentes propriétés, le calcul n'inclut que les entités qui contiennent toutes ces propriétés. Cela peut entraîner des résultats différents de ceux obtenus en effectuant chaque agrégation séparément.
Tarifs
Le prix des requêtes d'agrégation count()
, sum()
et avg()
dépend du nombre d'entrées d'index analysées lors de l'opération. Vous êtes facturé une lecture d'entité pour un maximum de 1 000 entrées d'index correspondantes. Les entrées d'index suivantes qui correspondent entraînent des unités de lecture supplémentaires. Un coût minimal d'une unité de lecture est appliqué à chaque requête. Pour connaître les tarifs, consultez la page Tarifs de Firestore en mode Datastore.
Si vous combinez plusieurs agrégations dans une même requête, celle-ci utilise le même index pour chaque agrégation et effectue une seule analyse des données. Cela peut aider à réduire le nombre d'analyses et de lectures d'index facturées par rapport à l'exécution de chaque agrégation séparément. Toutefois, les requêtes comportant plusieurs agrégations n'incluent que les entités qui contiennent toutes ces propriétés. Cela peut entraîner des résultats différents de ceux obtenus en effectuant chaque agrégation séparément.
Étapes suivantes
- En savoir plus sur les requêtes.
- Découvrez les bonnes pratiques pour Firestore en mode Datastore.