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 de récupérer 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 donné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
.
Le formulaire simplifié 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 par exemple utiliser cette fonctionnalité pour arrêter le comptage à 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
.
Le formulaire simplifié 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 la somme de la propriété spécifiée avec une valeur numérique dans les entités correspondant aux filtres donnés.
Java
Python
Cette requête nécessite un indice 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 numériques de la propriété des entités correspondant à 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 numériques de la propriété des entités correspondant aux filtres de requête.
Java
Python
Cette requête nécessite un indice 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 indice composite, et 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 seule 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 propose 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 travaillez avec 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 sous 60 secondes, une erreur
DEADLINE_EXCEEDED
est renvoyée. 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, vous pouvez 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 où la propriété de tri existe.En GQL, la forme simplifiée n'est pas compatible avec les clauses
ORDER BY
,LIMIT
ouOFFSET
.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 des données qu'à partir dea
oub
.Une agrégation
count()
ne déduplique pas les entités avec des propriétés de tableau. Chaque valeur du tableau correspondant à la requête ajoute un à la valeur du compteur.Pour les agrégations
sum()
etavg()
, les valeurs non numériques sont ignorées. L'agrégationsum()
etavg()
ne prend en compte que les valeurs entières, les valeurs à virgule flottante et les codes temporels. Les codes temporels sont convertis en valeurs entières de microsecondes poursum()
,avg()
et les projections.Lorsque vous combinez plusieurs agrégations dans une seule requête, notez que
sum()
etavg()
ignorent les valeurs non numériques, tandis quecount()
les inclut.Si vous combinez des agrégations sur 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 tarif 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. Une opération de lecture d'entité vous est facturée pour un maximum de 1 000 entrées d'index correspondant. Les entrées d'index ultérieures correspondant à des unités de lecture supplémentaires. Un coût minimal d'une unité de lecture vous est facturé pour chaque requête. Pour en savoir plus sur les tarifs, consultez la section Tarifs de Firestore en mode Datastore.
Si vous combinez plusieurs agrégations dans une seule requête, la requête utilise le même indice pour chaque agrégation et effectue une seule analyse des données. Cela peut vous aider à réduire le nombre d'analyses d'index et de lectures facturées par rapport à l'exécution de chaque agrégation séparément. Toutefois, les requêtes avec plusieurs agrégations n'incluent que les entités qui contiennent toutes ces propriétés. Cela peut donner des résultats différents de ceux obtenus en effectuant chaque agrégation séparément.
Étape suivante
- En savoir plus sur les requêtes.
- Découvrez les bonnes pratiques pour Firestore en mode Datastore.