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 votre code d'application et coûtent moins cher que la récupération de chaque entité à traiter. Lisez cette page pour apprendre à utiliser les requêtes d'agrégation.
Agrégation de 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 dans un genre.
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 de requêtes count()
:
SELECT COUNT(*) AS total FROM tasks
Cet exemple utilise un alias facultatif total
.
Le formulaire simplifié n'accepte que les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence de GQL.
L'agrégation count()
prend en compte les filtres appliqués à la requête et 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 de requêtes count()
:
SELECT COUNT(*) AS total FROM tasks WHERE is_done = false AND tag = 'house'
Cet exemple utilise un alias facultatif total
.
Le formulaire simplifié n'accepte que les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence de GQL.
Cet exemple montre comment compter jusqu'à une certaine valeur. Vous pouvez l'utiliser, par exemple, pour arrêter de compter à 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 de 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 total
.
Le formulaire simplifié n'accepte que les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence de GQL.
Agrégation de 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 d'une propriété donnée à partir d'entités du genre 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 de requêtes sum()
:
SELECT SUM(hours) AS total_hours FROM tasks
Cet exemple utilise un alias facultatif total_hours
.
Le formulaire simplifié n'accepte que les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence de GQL.
L'agrégation sum()
prend en compte les filtres appliqués à la requête et 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 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 de requêtes sum()
:
SELECT SUM(hours) AS total_hours FROM tasks WHERE is_done = false AND tag = 'house'
Cet exemple utilise un alias facultatif total_hours
.
Le formulaire simplifié n'accepte que les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence de GQL.
Agrégation de 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 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 de requêtes avg()
:
SELECT AVG(hours) as avg_hours
Cet exemple utilise un alias facultatif avg_hours
.
Le formulaire simplifié n'accepte que les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence de GQL.
L'agrégation avg()
prend en compte les filtres appliqués à la requête et 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 correspondant 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 de requêtes avg()
:
SELECT AVG(hours) as avg_hours FROM tasks WHERE is_done = false AND tag = 'house'
Cet exemple utilise un alias facultatif avg_hours
.
Le formulaire simplifié n'accepte que les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence de 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 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 accepte 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 de total_hours
et total_tasks
.
Le formulaire simplifié n'accepte que les clauses FROM
et WHERE
. Pour en savoir plus, consultez la documentation de référence de GQL.
Les requêtes avec agrégations multiples n'incluent que les entités qui contiennent toutes les propriétés de chaque agrégation. Cela peut conduire à des résultats différents en effectuant chaque agrégation séparément.
Comportement et limites
Lorsque vous utilisez des requêtes d'agrégation, tenez compte du comportement et des limites suivants:
- La requête que vous fournissez à l'agrégation doit respecter les restrictions sur les 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 de contournement possible consiste à utiliser des cursors 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.Dans GQL, le formulaire simplifié n'accepte pas les clauses
ORDER BY
,LIMIT
ouOFFSET
.Dans une requête de projection, vous ne pouvez agréger les données qu'à partir 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 comportant des propriétés de tableau. Chaque valeur de tableau correspondant à la requête en ajoute une au nombre.Pour les agrégations
sum()
etavg()
, les valeurs non numériques sont ignorées. L'agrégationsum()
etavg()
ne tient compte que des valeurs entières, des nombres à virgule flottante et des horodatages. Les codes temporels sont convertis en valeurs entières de 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()
inclut des valeurs non numériques.Si vous combinez des agrégations qui se trouvent sur des propriétés différentes, le calcul n'inclut que les entités contenant toutes ces propriétés. Cela peut entraîner des résultats différents en effectuant chaque agrégation séparément.
Tarification
La tarification 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 lecture d'entité vous est facturée pour un maximum de 1 000 entrées d'index correspondantes. Les entrées d'index suivantes
coûtent des unités de lecture supplémentaires. Un coût minimal s'élève à une unité de lecture par requête. Pour plus d'informations sur la tarification, consultez la section Tarifs de Firestore en mode Datastore.
Si vous combinez plusieurs agrégations dans une seule requête, celle-ci utilise le même index pour chaque agrégation et effectue une seule analyse des données. Cela peut vous 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 conduire à des résultats différents 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.