Une requête d'agrégation traite les données de plusieurs entrées d'index pour renvoyer une seule valeur récapitulative.
Cloud Firestore prend en charge les requêtes d'agrégation suivantes :
-
count()
-
sum()
-
average()
Cloud Firestore calcule l'agrégation et transmet uniquement le résultat à votre application. Par rapport à l'exécution d'une requête complète et au calcul de l'agrégation dans votre application, les requêtes d'agrégation permettent d'économiser à la fois sur les lectures de documents facturés et sur les octets transférés.
Les requêtes d'agrégation s'appuient sur la configuration d'index existante que vos requêtes utilisent déjà et évoluent proportionnellement au nombre d'entrées d'index analysées. La latence augmente avec le nombre d'éléments dans l'agrégation.
Utiliser l'agrégation count()
La requête d'agrégation count()
vous permet de déterminer le nombre de documents dans une collection ou une requête.
Reportez-vous aux exemples de données que nous avons configurés dans Obtenir des données .
L'agrégation count()
suivante renvoie le nombre total de villes dans la collection cities
.
Web modular API
const coll = collection(db, "cities"); const snapshot = await getCountFromServer(coll); console.log('count: ', snapshot.data().count);
Rapide
let query = db.collection("cities") let countQuery = query.count do { let snapshot = try await countQuery.getAggregation(source: .server) print(snapshot.count) } catch { print(error) }
Objectif c
FIRCollectionReference *query = [self.db collectionWithPath:@"cities"]; [query.count aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching count: %@", error); } else { NSLog(@"Cities count: %@", snapshot.count); } }];
Java
Query query = db.collection("cities"); AggregateQuery countQuery = query.count(); countQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Count fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Count: " + snapshot.getCount()); } else { Log.d(TAG, "Count failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities") val countQuery = query.count() countQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Count fetched successfully val snapshot = task.result Log.d(TAG, "Count: ${snapshot.count}") } else { Log.d(TAG, "Count failed: ", task.getException()) } }
Dart
// Returns number of documents in users collection db.collection("users").count().get().then( (res) => print(res.count), onError: (e) => print("Error completing: $e"), );
Aller
Java
CollectionReference collection = db.collection("cities"); AggregateQuerySnapshot snapshot = collection.count().get().get(); System.out.println("Count: " + snapshot.getCount());
Noeud.js
const collectionRef = db.collection('cities'); const snapshot = await collectionRef.count().get(); console.log(snapshot.data().count);
Python
L'agrégation count()
prend en compte les éventuels filtres sur la requête et les éventuelles clauses limit
.
Web modular API
const coll = collection(db, "cities"); const q = query(coll, where("state", "==", "CA")); const snapshot = await getCountFromServer(q); console.log('count: ', snapshot.data().count);
Rapide
let query = db.collection("cities").whereField("state", isEqualTo: "CA") let countQuery = query.count do { let snapshot = try await countQuery.getAggregation(source: .server) print(snapshot.count) } catch { print(error) }
Objectif c
FIRQuery *query = [[self.db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"]; [query.count aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching count: %@", error); } else { NSLog(@"Cities count: %@", snapshot.count); } }];
Java
Query query = db.collection("cities").whereEqualTo("state", "CA"); AggregateQuery countQuery = query.count(); countQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Count fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Count: " + snapshot.getCount()); } else { Log.d(TAG, "Count failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities").whereEqualTo("state", "CA") val countQuery = query.count() countQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Count fetched successfully val snapshot = task.result Log.d(TAG, "Count: ${snapshot.count}") } else { Log.d(TAG, "Count failed: ", task.getException()) } }
Dart
// This also works with collectionGroup queries. db.collection("users").where("age", isGreaterThan: 10).count().get().then( (res) => print(res.count), onError: (e) => print("Error completing: $e"), );
Aller
Java
CollectionReference collection = db.collection("cities"); Query query = collection.whereEqualTo("state", "CA"); AggregateQuerySnapshot snapshot = query.count().get().get(); System.out.println("Count: " + snapshot.getCount());
Noeud.js
const collectionRef = db.collection('cities'); const query = collectionRef.where('state', '==', 'CA'); const snapshot = await query.count().get(); console.log(snapshot.data().count);
Python
Utiliser l'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 :
Web modular API
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { totalPopulation: sum('population') }); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Rapide
let query = db.collection("cities") let aggregateQuery = query.aggregate([AggregateField.sum("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print(snapshot.get(AggregateField.sum("population"))) } catch { print(error) }
Objectif c
FIRQuery *query = [self.db collectionWithPath:@"cities"]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForSumOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]); } }];
Java
Query query = db.collection("cities"); AggregateQuery aggregateQuery = query.aggregate(AggregateField.sum("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities") val aggregateQuery = query.aggregate(AggregateField.sum("population")) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Java
collection = db.collection("cities"); snapshot = collection.aggregate(sum("population")).get().get(); System.out.println("Sum: " + snapshot.get(sum("population")));
Noeud.js
const coll = firestore.collection('cities'); const sumAggregateQuery = coll.aggregate({ totalPopulation: AggregateField.sum('population'), }); const snapshot = await sumAggregateQuery.get(); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Python
collection_ref = client.collection("users") aggregate_query = aggregation.AggregationQuery(collection_ref) aggregate_query.sum("coins", alias="sum") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Sum of results from query: {result[0].value}")
Aller
func createSumQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850) aggregationQuery := query.NewAggregationQuery().WithSum("coins", "sum_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } sum, ok := results["sum_coins"] if !ok { return errors.New("firestore: couldn't get alias for SUM from results") } sumValue := sum.(*firestorepb.Value) fmt.Fprintf(w, "Sum of results from query: %d\n", sumValue.GetIntegerValue()) return nil }
L'agrégation sum()
prend en compte tous les filtres sur la requête et toutes les clauses limit, par exemple :
Web modular API
const coll = collection(firestore, 'cities'); const q = query(coll, where('capital', '==', true)); const snapshot = await getAggregateFromServer(q, { totalPopulation: sum('population') }); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Rapide
let query = db.collection("cities").whereField("capital", isEqualTo: true) let aggregateQuery = query.aggregate([AggregateField.sum("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print(snapshot.get(AggregateField.sum("population"))) } catch { print(error) }
Objectif c
FIRQuery *query = [[self.db collectionWithPath:@"cities"] queryWhereFilter:[FIRFilter filterWhereField:@"capital" isEqualTo:@YES]]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForSumOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]); } }];
Java
Query query = db.collection("cities").whereEqualTo("capital", true); AggregateQuery aggregateQuery = query.aggregate(AggregateField.sum("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities").whereEqualTo("capital", true) val aggregateQuery = query.aggregate(AggregateField.sum("population")) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Java
collection = db.collection("cities"); query = collection.whereEqualTo("state", "CA"); snapshot = query.aggregate(sum("population")).get().get(); System.out.println("Sum: " + snapshot.get(sum("population")));
Noeud.js
const coll = firestore.collection('cities'); const q = coll.where("capital", "==", true); const sumAggregateQuery = q.aggregate({ totalPopulation: AggregateField.sum('population'), }); const snapshot = await sumAggregateQuery.get(); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Python
collection_ref = client.collection("users") query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew")) aggregate_query = aggregation.AggregationQuery(query) aggregate_query.sum("coins", alias="sum") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Sum of results from query: {result[0].value}")
Aller
func createSumQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850).Limit(5) aggregationQuery := query.NewAggregationQuery().WithSum("coins", "sum_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } sum, ok := results["sum_coins"] if !ok { return errors.New("firestore: couldn't get alias for SUM from results") } sumValue := sum.(*firestorepb.Value) fmt.Fprintf(w, "Sum of results from query: %d\n", sumValue.GetIntegerValue()) return nil }
Utiliser l'agrégation average()
Utilisez l'agrégation average()
pour renvoyer la moyenne des valeurs numériques correspondant à une requête donnée, par exemple :
Web modular API
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { averagePopulation: average('population') }); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Rapide
let query = db.collection("cities") let aggregateQuery = query.aggregate([AggregateField.average("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print(snapshot.get(AggregateField.average("population"))) } catch { print(error) }
Objectif c
FIRQuery *query = [self.db collectionWithPath:@"cities"]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]); } }];
Java
Query query = db.collection("cities"); AggregateQuery aggregateQuery = query.aggregate(AggregateField.average("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities") val aggregateQuery = query.aggregate(AggregateField.average("population")) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Java
collection = db.collection("cities"); snapshot = collection.aggregate(average("population")).get().get(); System.out.println("Average: " + snapshot.get(average("population")));
Noeud.js
const coll = firestore.collection('cities'); const averageAggregateQuery = coll.aggregate({ averagePopulation: AggregateField.average('population'), }); const snapshot = await averageAggregateQuery.get(); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Python
collection_ref = client.collection("users") aggregate_query = aggregation.AggregationQuery(collection_ref) aggregate_query.avg("coins", alias="avg") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Average of results from query: {result[0].value}")
Aller
func createAvgQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850) aggregationQuery := query.NewAggregationQuery().WithAvg("coins", "avg_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } avg, ok := results["avg_coins"] if !ok { return errors.New("firestore: couldn't get alias for AVG from results") } avgValue := avg.(*firestorepb.Value) fmt.Fprintf(w, "Avg of results from query: %d\n", avgValue.GetDoubleValue()) return nil }
L'agrégation average()
prend en compte tous les filtres sur la requête et toutes les clauses de limite, par exemple :
Web modular API
const coll = collection(firestore, 'cities'); const q = query(coll, where('capital', '==', true)); const snapshot = await getAggregateFromServer(q, { averagePopulation: average('population') }); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Rapide
let query = db.collection("cities").whereField("capital", isEqualTo: true) let aggregateQuery = query.aggregate([AggregateField.average("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print(snapshot.get(AggregateField.average("population"))) } catch { print(error) }
Objectif c
FIRQuery *query = [[self.db collectionWithPath:@"cities"] queryWhereFilter:[FIRFilter filterWhereField:@"capital" isEqualTo:@YES]]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]); } }];
Java
Query query = db.collection("cities").whereEqualTo("capital", true); AggregateQuery aggregateQuery = query.aggregate(AggregateField.average("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities").whereEqualTo("capital", true) val aggregateQuery = query.aggregate(AggregateField.average("population")) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Java
collection = db.collection("cities"); query = collection.whereEqualTo("state", "CA"); snapshot = query.aggregate(average("population")).get().get(); System.out.println("Average: " + snapshot.get(average("population")));
Noeud.js
const coll = firestore.collection('cities'); const q = coll.where("capital", "==", true); const averageAggregateQuery = q.aggregate({ averagePopulation: AggregateField.average('population'), }); const snapshot = await averageAggregateQuery.get(); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Python
collection_ref = client.collection("users") query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew")) aggregate_query = aggregation.AggregationQuery(query) aggregate_query.avg("coins", alias="avg") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Average of results from query: {result[0].value}")
Aller
func createAvgQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850).Limit(5) aggregationQuery := query.NewAggregationQuery().WithAvg("coins", "avg_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } avg, ok := results["avg_coins"] if !ok { return errors.New("firestore: couldn't get alias for AVG from results") } avgValue := avg.(*firestorepb.Value) fmt.Fprintf(w, "Avg of results from query: %d\n", avgValue.GetDoubleValue()) return nil }
Calculer plusieurs agrégations dans une requête
Vous pouvez combiner plusieurs agrégations dans un seul 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, la requête peut nécessiter un index composite. Dans ce cas, Cloud Firestore suggère un index.
L'exemple suivant effectue plusieurs agrégations dans une seule requête d'agrégation :
Web modular API
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { countOfDocs: count(), totalPopulation: sum('population'), averagePopulation: average('population') }); console.log('countOfDocs: ', snapshot.data().countOfDocs); console.log('totalPopulation: ', snapshot.data().totalPopulation); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Rapide
let query = db.collection("cities") let aggregateQuery = query.aggregate([ AggregateField.count(), AggregateField.sum("population"), AggregateField.average("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print("Count: \(snapshot.get(AggregateField.count()))") print("Sum: \(snapshot.get(AggregateField.sum("population")))") print("Average: \(snapshot.get(AggregateField.average("population")))") } catch { print(error) }
Objectif c
FIRQuery *query = [self.db collectionWithPath:@"cities"]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForCount], [FIRAggregateField aggregateFieldForSumOfField:@"population"], [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Count: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]]); NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]); NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]); } }];
Java
Query query = db.collection("cities"); AggregateQuery aggregateQuery = query.aggregate( AggregateField.count(), AggregateField.sum("population"), AggregateField.average("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Count: " + snapshot.get(AggregateField.count())); Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population"))); Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities") val aggregateQuery = query.aggregate( AggregateField.count(), AggregateField.sum("population"), AggregateField.average("population") ) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Count: ${snapshot.get(AggregateField.count())}") Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}") Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Java
collection = db.collection("cities"); query = collection.whereEqualTo("state", "CA"); AggregateQuery aggregateQuery = query.aggregate(count(), sum("population"), average("population")); snapshot = aggregateQuery.get().get(); System.out.println("Count: " + snapshot.getCount()); System.out.println("Sum: " + snapshot.get(sum("population"))); System.out.println("Average: " + snapshot.get(average("population")));
Noeud.js
const coll = firestore.collection('cities'); const aggregateQuery = coll.aggregate({ countOfDocs: AggregateField.count(), totalPopulation: AggregateField.sum('population'), averagePopulation: AggregateField.average('population') }); const snapshot = await aggregateQuery.get(); console.log('countOfDocs: ', snapshot.data().countOfDocs); console.log('totalPopulation: ', snapshot.data().totalPopulation); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Python
collection_ref = client.collection("users") query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew")) aggregate_query = aggregation.AggregationQuery(query) aggregate_query.sum("coins", alias="sum").avg("coins", alias="avg") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Aggregation of results from query: {result[0].value}")
Aller
func createMultiAggregationQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850) aggregationQuery := query.NewAggregationQuery().WithCount("count").WithSum("coins", "sum_coins").WithAvg("coins", "avg_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } }
Les requêtes avec plusieurs agrégations incluent uniquement les documents contenant tous les champs de chaque agrégation. Cela pourrait conduire à des résultats différents en effectuant chaque agrégation séparément.
Règles de sécurité pour les requêtes d'agrégation
Les règles de sécurité Cloud Firestore fonctionnent de la même manière sur les requêtes d'agrégation que sur les requêtes qui renvoient des documents. En d’autres termes, si et seulement si vos règles autorisent les clients à exécuter certaines requêtes de collection ou de groupe de collections, les clients peuvent également effectuer l’agrégation sur ces requêtes. Apprenez-en davantage sur la manière dont les règles de sécurité Cloud Firestore interagissent avec les requêtes .
Comportement et limites
Lorsque vous travaillez avec des requêtes d'agrégation, notez le comportement et les limitations suivants :
Vous ne pouvez pas utiliser de requêtes d'agrégation avec des écouteurs en temps réel et des requêtes hors ligne. Les requêtes d'agrégation ne sont prises en charge que via une réponse directe du serveur. Les requêtes sont servies uniquement par le backend Cloud Firestore, en ignorant le cache local et les mises à jour mises en mémoire tampon. Ce comportement est identique aux opérations effectuées dans les transactions Cloud Firestore .
Si une agrégation ne parvient 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 terminée dans le délai de 60 secondes, une solution possible consiste à utiliser des compteurs pour les grands ensembles de données.
Les requêtes d'agrégation lisent à partir des entrées d'index et incluent uniquement les champs indexés.
L'ajout d'une clause
OrderBy
à une requête d'agrégation limite l'agrégation aux documents pour lesquels le champ de tri existe.Pour les agrégations
sum()
etaverage()
, les valeurs non numériques sont ignorées. Les agrégationssum()
etaverage()
ne prennent en compte que les valeurs entières et les valeurs numériques à virgule flottante.Lorsque vous combinez plusieurs agrégations dans une seule requête, notez que
sum()
etaverage()
ignorent les valeurs non numériques tandis quecount()
inclut des valeurs non numériques.Si vous combinez des agrégations qui se trouvent sur différents champs, le calcul inclut uniquement les documents contenant tous ces champs.
Tarifs
La tarification des requêtes d'agrégation dépend du nombre d'entrées d'index correspondant à la requête. Un petit nombre de lectures vous est facturé pour un grand nombre d'entrées correspondantes.
Voir des informations de prix plus détaillées.