Summarize data with aggregation queries Stay organized with collections Save and categorize content based on your preferences.
An aggregation query processes the data from multiple index entries to return asingle summary value.
Cloud Firestore supports the followingaggregation queries:
count()
sum()
average()
Cloud Firestore calculates the aggregation and transmits only the resultback to your application. Compared to executing a full query and calculating theaggregation in your app, aggregation queries save on both billed document readsand bytes transferred.
Aggregation queries rely on the existing index configuration thatyour queries already use, and scale proportionally to the number of indexentries scanned. Latency increases with the number of itemsin the aggregation.
Note: While the code samples cover multiple languages, the text explaining thesamples refers to the Web method names.Use thecount()
aggregation
Thecount()
aggregation query lets youdetermine the number of documents in a collection or query.
For more information about the example data, seeGetting data.
The followingcount()
aggregation returns the total number of cities in thecities
collection.
Web
Learn more about the tree-shakeable Web v9 modular SDK andupgrade from version 8.constcoll=collection(db,"cities");constsnapshot=awaitgetCountFromServer(coll);console.log('count: ',snapshot.data().count);
Swift
letquery=db.collection("cities")letcountQuery=query.countdo{letsnapshot=tryawaitcountQuery.getAggregation(source:.server)print(snapshot.count)}catch{print(error)}
Objective-C
FIRCollectionReference*query=[self.dbcollectionWithPath:@"cities"];[query.countaggregationWithSource:FIRAggregateSourceServercompletion:^(FIRAggregateQuerySnapshot*snapshot,NSError*error){if(error!=nil){NSLog(@"Error fetching count: %@",error);}else{NSLog(@"Cities count: %@",snapshot.count);}}];
Java
Queryquery=db.collection("cities");AggregateQuerycountQuery=query.count();countQuery.get(AggregateSource.SERVER).addOnCompleteListener(newOnCompleteListener<AggregateQuerySnapshot>(){@OverridepublicvoidonComplete(@NonNullTask<AggregateQuerySnapshot>task){if(task.isSuccessful()){// Count fetched successfullyAggregateQuerySnapshotsnapshot=task.getResult();Log.d(TAG,"Count: "+snapshot.getCount());}else{Log.d(TAG,"Count failed: ",task.getException());}}});
Kotlin
valquery=db.collection("cities")valcountQuery=query.count()countQuery.get(AggregateSource.SERVER).addOnCompleteListener{task->if(task.isSuccessful){// Count fetched successfullyvalsnapshot=task.resultLog.d(TAG,"Count:${snapshot.count}")}else{Log.d(TAG,"Count failed: ",task.getException())}}
Dart
// Returns number of documents in users collectiondb.collection("cities").count().get().then((res)=>print(res.count),onError:(e)=>print("Error completing:$e"),);
Go
packagefirestoreimport("context""errors""fmt""io""cloud.google.com/go/firestore"firestorepb"cloud.google.com/go/firestore/apiv1/firestorepb")funccreateCountQuery(wio.Writer,projectIDstring)error{// Instantiate the clientctx:=context.Background()client,err:=firestore.NewClient(ctx,projectID)iferr!=nil{returnerr}deferclient.Close()collection:=client.Collection("users")query:=collection.Where("born",">",1850)// `alias` argument--"all"--provides a key for accessing the aggregate query// results. The alias value must be unique across all aggregation aliases in// an aggregation query and must conform to allowed Document field names.//// See https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#document for details.aggregationQuery:=query.NewAggregationQuery().WithCount("all")results,err:=aggregationQuery.Get(ctx)iferr!=nil{returnerr}count,ok:=results["all"]if!ok{returnerrors.New("firestore: couldn't get alias for COUNT from results")}countValue:=count.(*firestorepb.Value)fmt.Fprintf(w,"Number of results from query: %d\n",countValue.GetIntegerValue())returnnil}
Java
CollectionReferencecollection=db.collection("cities");AggregateQuerySnapshotsnapshot=collection.count().get().get();System.out.println("Count: "+snapshot.getCount());
Node.js
constcollectionRef=db.collection('cities');constsnapshot=awaitcollectionRef.count().get();console.log(snapshot.data().count);
Python
fromgoogle.cloudimportfirestorefromgoogle.cloud.firestore_v1importaggregationfromgoogle.cloud.firestore_v1.base_queryimportFieldFilterdefcreate_count_query(project_id:str)->None:"""Builds an aggregate query that returns the number of results in the query. Arguments: project_id: your Google Cloud Project ID """client=firestore.Client(project=project_id)collection_ref=client.collection("users")query=collection_ref.where(filter=FieldFilter("born",">",1800))aggregate_query=aggregation.AggregationQuery(query)# `alias` to provides a key for accessing the aggregate query resultsaggregate_query.count(alias="all")results=aggregate_query.get()forresultinresults:print(f"Alias of results from query:{result[0].alias}")print(f"Number of results from query:{result[0].value}")
Thecount()
aggregation takes into account any filters on the query and anylimit
clauses.
Web
Learn more about the tree-shakeable Web v9 modular SDK andupgrade from version 8.constcoll=collection(db,"cities");constq=query(coll,where("state","==","CA"));constsnapshot=awaitgetCountFromServer(q);console.log('count: ',snapshot.data().count);
Swift
letquery=db.collection("cities").whereField("state",isEqualTo:"CA")letcountQuery=query.countdo{letsnapshot=tryawaitcountQuery.getAggregation(source:.server)print(snapshot.count)}catch{print(error)}
Objective-C
FIRQuery*query=[[self.dbcollectionWithPath:@"cities"]queryWhereField:@"state"isEqualTo:@"CA"];[query.countaggregationWithSource:FIRAggregateSourceServercompletion:^(FIRAggregateQuerySnapshot*snapshot,NSError*error){if(error!=nil){NSLog(@"Error fetching count: %@",error);}else{NSLog(@"Cities count: %@",snapshot.count);}}];
Java
Queryquery=db.collection("cities").whereEqualTo("state","CA");AggregateQuerycountQuery=query.count();countQuery.get(AggregateSource.SERVER).addOnCompleteListener(newOnCompleteListener<AggregateQuerySnapshot>(){@OverridepublicvoidonComplete(@NonNullTask<AggregateQuerySnapshot>task){if(task.isSuccessful()){// Count fetched successfullyAggregateQuerySnapshotsnapshot=task.getResult();Log.d(TAG,"Count: "+snapshot.getCount());}else{Log.d(TAG,"Count failed: ",task.getException());}}});
Kotlin
valquery=db.collection("cities").whereEqualTo("state","CA")valcountQuery=query.count()countQuery.get(AggregateSource.SERVER).addOnCompleteListener{task->if(task.isSuccessful){// Count fetched successfullyvalsnapshot=task.resultLog.d(TAG,"Count:${snapshot.count}")}else{Log.d(TAG,"Count failed: ",task.getException())}}
Dart
// This also works with collection queries.db.collection("cities").where("capital",isEqualTo:10).count().get().then((res)=>print(res.count),onError:(e)=>print("Error completing:$e"),);
Go
packagefirestoreimport("context""errors""fmt""io""cloud.google.com/go/firestore"firestorepb"cloud.google.com/go/firestore/apiv1/firestorepb")funccreateCountQuery(wio.Writer,projectIDstring)error{// Instantiate the clientctx:=context.Background()client,err:=firestore.NewClient(ctx,projectID)iferr!=nil{returnerr}deferclient.Close()collection:=client.Collection("users")query:=collection.Where("born",">",1850)// `alias` argument--"all"--provides a key for accessing the aggregate query// results. The alias value must be unique across all aggregation aliases in// an aggregation query and must conform to allowed Document field names.//// See https://cloud.google.com/firestore/docs/reference/rpc/google.firestore.v1#document for details.aggregationQuery:=query.NewAggregationQuery().WithCount("all")results,err:=aggregationQuery.Get(ctx)iferr!=nil{returnerr}count,ok:=results["all"]if!ok{returnerrors.New("firestore: couldn't get alias for COUNT from results")}countValue:=count.(*firestorepb.Value)fmt.Fprintf(w,"Number of results from query: %d\n",countValue.GetIntegerValue())returnnil}
Java
CollectionReferencecollection=db.collection("cities");Queryquery=collection.whereEqualTo("state","CA");AggregateQuerySnapshotsnapshot=query.count().get().get();System.out.println("Count: "+snapshot.getCount());
Node.js
constcollectionRef=db.collection('cities');constquery=collectionRef.where('state','==','CA');constsnapshot=awaitquery.count().get();console.log(snapshot.data().count);
Python
fromgoogle.cloudimportfirestorefromgoogle.cloud.firestore_v1importaggregationfromgoogle.cloud.firestore_v1.base_queryimportFieldFilterdefcreate_count_query(project_id:str)->None:"""Builds an aggregate query that returns the number of results in the query. Arguments: project_id: your Google Cloud Project ID """client=firestore.Client(project=project_id)collection_ref=client.collection("users")query=collection_ref.where(filter=FieldFilter("born",">",1800))aggregate_query=aggregation.AggregationQuery(query)# `alias` to provides a key for accessing the aggregate query resultsaggregate_query.count(alias="all")results=aggregate_query.get()forresultinresults:print(f"Alias of results from query:{result[0].alias}")print(f"Number of results from query:{result[0].value}")
Use thesum()
aggregation
Use thesum()
aggregation to return the total sum of numeric values thatmatch a given query—for example:
Web
Learn more about the tree-shakeable Web v9 modular SDK andupgrade from version 8.constcoll=collection(firestore,'cities');constsnapshot=awaitgetAggregateFromServer(coll,{totalPopulation:sum('population')});console.log('totalPopulation: ',snapshot.data().totalPopulation);
Swift
letquery=db.collection("cities")letaggregateQuery=query.aggregate([AggregateField.sum("population")])do{letsnapshot=tryawaitaggregateQuery.getAggregation(source:.server)print(snapshot.get(AggregateField.sum("population")))}catch{print(error)}
Objective-C
FIRQuery*query=[self.dbcollectionWithPath:@"cities"];FIRAggregateQuery*aggregateQuery=[queryaggregate:@[[FIRAggregateFieldaggregateFieldForSumOfField:@"population"]]];[aggregateQueryaggregationWithSource:FIRAggregateSourceServercompletion:^(FIRAggregateQuerySnapshot*snapshot,NSError*error){if(error!=nil){NSLog(@"Error fetching aggregate: %@",error);}else{NSLog(@"Sum: %@",[snapshotvalueForAggregateField:[FIRAggregateFieldaggregateFieldForSumOfField:@"population"]]);}}];
Java
Queryquery=db.collection("cities");AggregateQueryaggregateQuery=query.aggregate(AggregateField.sum("population"));aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(newOnCompleteListener<AggregateQuerySnapshot>(){@OverridepublicvoidonComplete(@NonNullTask<AggregateQuerySnapshot>task){if(task.isSuccessful()){// Aggregate fetched successfullyAggregateQuerySnapshotsnapshot=task.getResult();Log.d(TAG,"Sum: "+snapshot.get(AggregateField.sum("population")));}else{Log.d(TAG,"Aggregation failed: ",task.getException());}}});
Kotlin
valquery=db.collection("cities")valaggregateQuery=query.aggregate(AggregateField.sum("population"))aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener{task->if(task.isSuccessful){// Aggregate fetched successfullyvalsnapshot=task.resultLog.d(TAG,"Sum:${snapshot.get(AggregateField.sum("population"))}")}else{Log.d(TAG,"Aggregate failed: ",task.getException())}}
Dart
db.collection("cities").aggregate(sum("population")).get().then((res)=>print(res.getAverage("population")),onError:(e)=>print("Error completing:$e"),);
Java
collection=db.collection("cities");snapshot=collection.aggregate(sum("population")).get().get();System.out.println("Sum: "+snapshot.get(sum("population")));
Node.js
constcoll=firestore.collection('cities');constsumAggregateQuery=coll.aggregate({totalPopulation:AggregateField.sum('population'),});constsnapshot=awaitsumAggregateQuery.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()forresultinresults:print(f"Alias of results from query: {result[0].alias}")print(f"Sum of results from query: {result[0].value}")
Go
funccreateSumQuery(wio.Writer,projectIDstring)error{ctx:=context.Background()client,err:=firestore.NewClient(ctx,projectID)iferr!=nil{returnerr}deferclient.Close()collection:=client.Collection("users")query:=collection.Where("born",">",1850)aggregationQuery:=query.NewAggregationQuery().WithSum("coins","sum_coins")results,err:=aggregationQuery.Get(ctx)iferr!=nil{returnerr}sum,ok:=results["sum_coins"]if!ok{returnerrors.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())returnnil}
Thesum()
aggregation takes into account any filters on the query and anylimit clauses—for example:
Web
Learn more about the tree-shakeable Web v9 modular SDK andupgrade from version 8.constcoll=collection(firestore,'cities');constq=query(coll,where('capital','==',true));constsnapshot=awaitgetAggregateFromServer(q,{totalPopulation:sum('population')});console.log('totalPopulation: ',snapshot.data().totalPopulation);
Swift
letquery=db.collection("cities").whereField("capital",isEqualTo:true)letaggregateQuery=query.aggregate([AggregateField.sum("population")])do{letsnapshot=tryawaitaggregateQuery.getAggregation(source:.server)print(snapshot.get(AggregateField.sum("population")))}catch{print(error)}
Objective-C
FIRQuery*query=[[self.dbcollectionWithPath:@"cities"]queryWhereFilter:[FIRFilterfilterWhereField:@"capital"isEqualTo:@YES]];FIRAggregateQuery*aggregateQuery=[queryaggregate:@[[FIRAggregateFieldaggregateFieldForSumOfField:@"population"]]];[aggregateQueryaggregationWithSource:FIRAggregateSourceServercompletion:^(FIRAggregateQuerySnapshot*snapshot,NSError*error){if(error!=nil){NSLog(@"Error fetching aggregate: %@",error);}else{NSLog(@"Sum: %@",[snapshotvalueForAggregateField:[FIRAggregateFieldaggregateFieldForSumOfField:@"population"]]);}}];
Java
Queryquery=db.collection("cities").whereEqualTo("capital",true);AggregateQueryaggregateQuery=query.aggregate(AggregateField.sum("population"));aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(newOnCompleteListener<AggregateQuerySnapshot>(){@OverridepublicvoidonComplete(@NonNullTask<AggregateQuerySnapshot>task){if(task.isSuccessful()){// Aggregate fetched successfullyAggregateQuerySnapshotsnapshot=task.getResult();Log.d(TAG,"Sum: "+snapshot.get(AggregateField.sum("population")));}else{Log.d(TAG,"Aggregation failed: ",task.getException());}}});
Kotlin
valquery=db.collection("cities").whereEqualTo("capital",true)valaggregateQuery=query.aggregate(AggregateField.sum("population"))aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener{task->if(task.isSuccessful){// Aggregate fetched successfullyvalsnapshot=task.resultLog.d(TAG,"Sum:${snapshot.get(AggregateField.sum("population"))}")}else{Log.d(TAG,"Aggregate failed: ",task.getException())}}
Dart
db.collection("cities").where("capital",isEqualTo:true).aggregate(sum("population")).get().then((res)=>print(res.getAverage("population")),onError:(e)=>print("Error completing:$e"),);
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")));
Node.js
constcoll=firestore.collection('cities');constq=coll.where("capital","==",true);constsumAggregateQuery=q.aggregate({totalPopulation:AggregateField.sum('population'),});constsnapshot=awaitsumAggregateQuery.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()forresultinresults:print(f"Alias of results from query: {result[0].alias}")print(f"Sum of results from query: {result[0].value}")
Go
funccreateSumQuery(wio.Writer,projectIDstring)error{ctx:=context.Background()client,err:=firestore.NewClient(ctx,projectID)iferr!=nil{returnerr}deferclient.Close()collection:=client.Collection("users")query:=collection.Where("born",">",1850).Limit(5)aggregationQuery:=query.NewAggregationQuery().WithSum("coins","sum_coins")results,err:=aggregationQuery.Get(ctx)iferr!=nil{returnerr}sum,ok:=results["sum_coins"]if!ok{returnerrors.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())returnnil}
Use theaverage()
aggregation
Use theaverage()
aggregation to return the average of numeric values that match agiven query, for example:
Web
Learn more about the tree-shakeable Web v9 modular SDK andupgrade from version 8.constcoll=collection(firestore,'cities');constsnapshot=awaitgetAggregateFromServer(coll,{averagePopulation:average('population')});console.log('averagePopulation: ',snapshot.data().averagePopulation);
Swift
letquery=db.collection("cities")letaggregateQuery=query.aggregate([AggregateField.average("population")])do{letsnapshot=tryawaitaggregateQuery.getAggregation(source:.server)print(snapshot.get(AggregateField.average("population")))}catch{print(error)}
Objective-C
FIRQuery*query=[self.dbcollectionWithPath:@"cities"];FIRAggregateQuery*aggregateQuery=[queryaggregate:@[[FIRAggregateFieldaggregateFieldForAverageOfField:@"population"]]];[aggregateQueryaggregationWithSource:FIRAggregateSourceServercompletion:^(FIRAggregateQuerySnapshot*snapshot,NSError*error){if(error!=nil){NSLog(@"Error fetching aggregate: %@",error);}else{NSLog(@"Avg: %@",[snapshotvalueForAggregateField:[FIRAggregateFieldaggregateFieldForAverageOfField:@"population"]]);}}];
Java
Queryquery=db.collection("cities");AggregateQueryaggregateQuery=query.aggregate(AggregateField.average("population"));aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(newOnCompleteListener<AggregateQuerySnapshot>(){@OverridepublicvoidonComplete(@NonNullTask<AggregateQuerySnapshot>task){if(task.isSuccessful()){// Aggregate fetched successfullyAggregateQuerySnapshotsnapshot=task.getResult();Log.d(TAG,"Average: "+snapshot.get(AggregateField.average("population")));}else{Log.d(TAG,"Aggregation failed: ",task.getException());}}});
Kotlin
valquery=db.collection("cities")valaggregateQuery=query.aggregate(AggregateField.average("population"))aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener{task->if(task.isSuccessful){// Aggregate fetched successfullyvalsnapshot=task.resultLog.d(TAG,"Average:${snapshot.get(AggregateField.average("population"))}")}else{Log.d(TAG,"Aggregate failed: ",task.getException())}}
Dart
db.collection("cities").aggregate(average("population")).get().then((res)=>print(res.getAverage("population")),onError:(e)=>print("Error completing:$e"),);
Java
collection=db.collection("cities");snapshot=collection.aggregate(average("population")).get().get();System.out.println("Average: "+snapshot.get(average("population")));
Node.js
constcoll=firestore.collection('cities');constaverageAggregateQuery=coll.aggregate({averagePopulation:AggregateField.average('population'),});constsnapshot=awaitaverageAggregateQuery.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()forresultinresults:print(f"Alias of results from query: {result[0].alias}")print(f"Average of results from query: {result[0].value}")
Go
funccreateAvgQuery(wio.Writer,projectIDstring)error{ctx:=context.Background()client,err:=firestore.NewClient(ctx,projectID)iferr!=nil{returnerr}deferclient.Close()collection:=client.Collection("users")query:=collection.Where("born",">",1850)aggregationQuery:=query.NewAggregationQuery().WithAvg("coins","avg_coins")results,err:=aggregationQuery.Get(ctx)iferr!=nil{returnerr}avg,ok:=results["avg_coins"]if!ok{returnerrors.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())returnnil}
Theaverage()
aggregation takes into account any filters on the query and any limitclauses, for example:
Web
Learn more about the tree-shakeable Web v9 modular SDK andupgrade from version 8.constcoll=collection(firestore,'cities');constq=query(coll,where('capital','==',true));constsnapshot=awaitgetAggregateFromServer(q,{averagePopulation:average('population')});console.log('averagePopulation: ',snapshot.data().averagePopulation);
Swift
letquery=db.collection("cities").whereField("capital",isEqualTo:true)letaggregateQuery=query.aggregate([AggregateField.average("population")])do{letsnapshot=tryawaitaggregateQuery.getAggregation(source:.server)print(snapshot.get(AggregateField.average("population")))}catch{print(error)}
Objective-C
FIRQuery*query=[[self.dbcollectionWithPath:@"cities"]queryWhereFilter:[FIRFilterfilterWhereField:@"capital"isEqualTo:@YES]];FIRAggregateQuery*aggregateQuery=[queryaggregate:@[[FIRAggregateFieldaggregateFieldForAverageOfField:@"population"]]];[aggregateQueryaggregationWithSource:FIRAggregateSourceServercompletion:^(FIRAggregateQuerySnapshot*snapshot,NSError*error){if(error!=nil){NSLog(@"Error fetching aggregate: %@",error);}else{NSLog(@"Avg: %@",[snapshotvalueForAggregateField:[FIRAggregateFieldaggregateFieldForAverageOfField:@"population"]]);}}];
Java
Queryquery=db.collection("cities").whereEqualTo("capital",true);AggregateQueryaggregateQuery=query.aggregate(AggregateField.average("population"));aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(newOnCompleteListener<AggregateQuerySnapshot>(){@OverridepublicvoidonComplete(@NonNullTask<AggregateQuerySnapshot>task){if(task.isSuccessful()){// Aggregate fetched successfullyAggregateQuerySnapshotsnapshot=task.getResult();Log.d(TAG,"Average: "+snapshot.get(AggregateField.average("population")));}else{Log.d(TAG,"Aggregation failed: ",task.getException());}}});
Kotlin
valquery=db.collection("cities").whereEqualTo("capital",true)valaggregateQuery=query.aggregate(AggregateField.average("population"))aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener{task->if(task.isSuccessful){// Aggregate fetched successfullyvalsnapshot=task.resultLog.d(TAG,"Average:${snapshot.get(AggregateField.average("population"))}")}else{Log.d(TAG,"Aggregate failed: ",task.getException())}}
Dart
db.collection("cities").where("capital",isEqualTo:true).aggregate(average("population")).get().then((res)=>print(res.getAverage("population")),onError:(e)=>print("Error completing:$e"),);
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")));
Node.js
constcoll=firestore.collection('cities');constq=coll.where("capital","==",true);constaverageAggregateQuery=q.aggregate({averagePopulation:AggregateField.average('population'),});constsnapshot=awaitaverageAggregateQuery.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()forresultinresults:print(f"Alias of results from query: {result[0].alias}")print(f"Average of results from query: {result[0].value}")
Go
funccreateAvgQuery(wio.Writer,projectIDstring)error{ctx:=context.Background()client,err:=firestore.NewClient(ctx,projectID)iferr!=nil{returnerr}deferclient.Close()collection:=client.Collection("users")query:=collection.Where("born",">",1850).Limit(5)aggregationQuery:=query.NewAggregationQuery().WithAvg("coins","avg_coins")results,err:=aggregationQuery.Get(ctx)iferr!=nil{returnerr}avg,ok:=results["avg_coins"]if!ok{returnerrors.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())returnnil}
Calculate multiple aggregations in a query
You can combine multiple aggregations in a single aggregation pipeline. This canreduce the number of index reads required. If the query includes aggregations onmultiple fields, the query might requires a composite index. In that case,Cloud Firestore suggests an index.
The following example performs multiple aggregations in a single aggregation query:
Web
Learn more about the tree-shakeable Web v9 modular SDK andupgrade from version 8.constcoll=collection(firestore,'cities');constsnapshot=awaitgetAggregateFromServer(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);
Swift
letquery=db.collection("cities")letaggregateQuery=query.aggregate([AggregateField.count(),AggregateField.sum("population"),AggregateField.average("population")])do{letsnapshot=tryawaitaggregateQuery.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)}
Objective-C
FIRQuery*query=[self.dbcollectionWithPath:@"cities"];FIRAggregateQuery*aggregateQuery=[queryaggregate:@[[FIRAggregateFieldaggregateFieldForCount],[FIRAggregateFieldaggregateFieldForSumOfField:@"population"],[FIRAggregateFieldaggregateFieldForAverageOfField:@"population"]]];[aggregateQueryaggregationWithSource:FIRAggregateSourceServercompletion:^(FIRAggregateQuerySnapshot*snapshot,NSError*error){if(error!=nil){NSLog(@"Error fetching aggregate: %@",error);}else{NSLog(@"Count: %@",[snapshotvalueForAggregateField:[FIRAggregateFieldaggregateFieldForCount]]);NSLog(@"Sum: %@",[snapshotvalueForAggregateField:[FIRAggregateFieldaggregateFieldForSumOfField:@"population"]]);NSLog(@"Avg: %@",[snapshotvalueForAggregateField:[FIRAggregateFieldaggregateFieldForAverageOfField:@"population"]]);}}];
Java
Queryquery=db.collection("cities");AggregateQueryaggregateQuery=query.aggregate(AggregateField.count(),AggregateField.sum("population"),AggregateField.average("population"));aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(newOnCompleteListener<AggregateQuerySnapshot>(){@OverridepublicvoidonComplete(@NonNullTask<AggregateQuerySnapshot>task){if(task.isSuccessful()){// Aggregate fetched successfullyAggregateQuerySnapshotsnapshot=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
valquery=db.collection("cities")valaggregateQuery=query.aggregate(AggregateField.count(),AggregateField.sum("population"),AggregateField.average("population"))aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener{task->if(task.isSuccessful){// Aggregate fetched successfullyvalsnapshot=task.resultLog.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())}}
Dart
db.collection("cities").aggregate(count(),sum("population"),average("population"),).get().then((res){print(res.count);print(res.getSum("population"));print(res.getAverage("population"));},onError:(e)=>print("Error completing:$e"),);
Java
collection=db.collection("cities");query=collection.whereEqualTo("state","CA");AggregateQueryaggregateQuery=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")));
Node.js
constcoll=firestore.collection('cities');constaggregateQuery=coll.aggregate({countOfDocs:AggregateField.count(),totalPopulation:AggregateField.sum('population'),averagePopulation:AggregateField.average('population')});constsnapshot=awaitaggregateQuery.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()forresultinresults:print(f"Alias of results from query: {result[0].alias}")print(f"Aggregation of results from query: {result[0].value}")
Go
funccreateMultiAggregationQuery(wio.Writer,projectIDstring)error{ctx:=context.Background()client,err:=firestore.NewClient(ctx,projectID)iferr!=nil{returnerr}deferclient.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)iferr!=nil{returnerr}}
Queries with multiple aggregations include only the documents that contain allthe fields in each aggregation. This might lead to different results fromperforming each aggregation separately.
Security rules for aggregation queries
Cloud Firestore Security Rules work the same on aggregation queries as onqueries that return documents. In other words, if and only if your rules allowclients to execute certain collection or collection group queries, clients canalso perform the aggregation on those queries. Learn more abouthowCloud Firestore Security Rules interact with queries.
Behavior and limitations
As you work with aggregation queries, note the following behavior and limitations:
You can't use aggregation queries with real-time listeners and offlinequeries. Aggregation queries are only supported through a direct serverresponse. Queries are served only by theCloud Firestore backend, skippingthe local cache and any buffered updates. This behavior is identical tooperations that are performed insideCloud Firestoretransactions.
If an aggregation can't resolve within 60 seconds, it returns a
Note: Most queries scale based on the on the size ofthe result set, not the dataset. However, aggregation queries scale based onthe size of the dataset and the number of index entries scanned.DEADLINE_EXCEEDED
error. Performance depends on your index configuration andon the size of the dataset.If the operation can't be completed within the 60 second deadline, apossible workaround is to usecountersfor large datasets.
Aggregation queries read from index entries and include only indexedfields.
Adding an
OrderBy
clause to an aggregation query limits the aggregation tothe documents where the sorting field exists.For
sum()
andaverage()
aggregations, non-numeric values are ignored.sum()
andaverage()
aggregations take into account only integer values andfloating-point number values.When combining multiple aggregations in a single query, note that
sum()
andaverage()
ignore non-numeric values whilecount()
includes non-numeric values.If you combine aggregations that are on different fields, the calculationincludes only the documents that contain all those fields.
Pricing
Pricing for aggregation queries depends on the number of index entries that thequery matches. You are charged a small number of reads for a large number ofmatched entries. You are charged one read operation for each batch of up to 1000index entries read.
For more information about aggregation queries pricing, seeAggregation queries.
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-10-10 UTC.