<br />

An aggregation query processes the data from multiple index entries to return a single summary value.  

Cloud Firestoresupports the following aggregation queries:

- `count()`
- `sum()`
- `average()`

Cloud Firestorecalculates the aggregation and transmits only the result back to your application. Compared to executing a full query and calculating the aggregation in your app, aggregation queries save on both billed document reads and bytes transferred.

Aggregation queries rely on the existing index configuration that your queries already use, and scale proportionally to the number of index entries scanned. Latency increases with the number of items in the aggregation.
| **Note:** While the code samples cover multiple languages, the text explaining the samples refers to the Web method names.

## Use the`count()`aggregation

The`count()`aggregation query lets you determine the number of documents in a collection or query.

For more information about the example data, see[Getting data](https://firebase.google.com/docs/firestore/query-data/get-data).

The following`count()`aggregation returns the total number of cities in the`cities`collection.  

### Web

[Learn more](https://firebase.google.com/docs/web/learn-more#modular-version)about the tree-shakeable Web v9 modular SDK and[upgrade](https://firebase.google.com/docs/web/modular-upgrade)from version 8.  

```javascript
const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);https://github.com/firebase/snippets-web/blob/95c8c159ff4d90af442352f058406f1aeb8adcbb/snippets/firestore-next/test-firestore/count_aggregate_collection.js#L8-L10
```

##### Swift

**Note:**This product is not available on watchOS and App Clip targets.  

```swift
let query = db.collection("cities")
let countQuery = query.count
do {
  let snapshot = try await countQuery.getAggregation(source: .server)
  print(snapshot.count)
} catch {
  print(error)
}https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/swift/firestore-smoketest/ViewController.swift#L1276-L1283
```

##### Objective-C

**Note:**This product is not available on watchOS and App Clip targets.  

```objective-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);
    }
}];https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/objc/firestore-smoketest-objc/ViewController.m#L1172-L1181
```

### Java

```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());
        }
    }
});https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/DocSnippets.java#L1338-L1351
```

### Kotlin

```kotlin
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())
    }
}https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/kotlin/DocSnippets.kt#L1116-L1126
```

### Dart

```dart
// Returns number of documents in users collection
db.collection("cities").count().get().then(
      (res) => print(res.count),
      onError: (e) => print("Error completing: $e"),
    );https://github.com/firebase/snippets-flutter/blob/f674af111fe63779c39e79699f7d269231f77563/packages/firebase_snippets_app/lib/snippets/firestore.dart#L870-L874
```

##### Go

    package firestore

    import (
    	"context"
    	"errors"
    	"fmt"
    	"io"

    	"cloud.google.com/go/firestore"
    	firestorepb "cloud.google.com/go/firestore/apiv1/firestorepb"
    )

    func createCountQuery(w io.Writer, projectID string) error {

    	// Instantiate the client
    	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)

    	// `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)
    	if err != nil {
    		return err
    	}

    	count, ok := results["all"]
    	if !ok {
    		return errors.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())
    	return nil
    }  
    https://github.com/GoogleCloudPlatform/golang-samples/blob/2c9f7d4fe3c1b465d5285d558992506b46e78fd7/firestore/aggregate_query_count.go#L16-L61

##### Java

```java
CollectionReference collection = db.collection("cities");
AggregateQuerySnapshot snapshot = collection.count().get().get();
System.out.println("Count: " + snapshot.getCount());
      
```

##### Node.js

```javascript
const collectionRef = db.collection('cities');
const snapshot = await collectionRef.count().get();
console.log(snapshot.data().count);
      
```

##### Python

    from google.cloud import firestore
    from google.cloud.firestore_v1 import aggregation
    from google.cloud.firestore_v1.base_query import FieldFilter


    def create_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 results
        aggregate_query.count(alias="all")

        results = aggregate_query.get()
        for result in results:
            print(f"Alias of results from query: {result[0].alias}")
            print(f"Number of results from query: {result[0].value}")

    https://github.com/GoogleCloudPlatform/python-docs-samples/blob/eff0040dee2bab9c4684f8425aa4d8ef28a9a244/firestore/cloud-client/aggregate_query_count.py#L22-L47

The`count()`aggregation takes into account any filters on the query and any`limit`clauses.  

### Web

[Learn more](https://firebase.google.com/docs/web/learn-more#modular-version)about the tree-shakeable Web v9 modular SDK and[upgrade](https://firebase.google.com/docs/web/modular-upgrade)from version 8.  

```javascript
const coll = collection(db, "cities");
const q = query(coll, where("state", "==", "CA"));
const snapshot = await getCountFromServer(q);
console.log('count: ', snapshot.data().count);https://github.com/firebase/snippets-web/blob/95c8c159ff4d90af442352f058406f1aeb8adcbb/snippets/firestore-next/test-firestore/count_aggregate_query.js#L8-L11
```

##### Swift

**Note:**This product is not available on watchOS and App Clip targets.  

```swift
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)
}https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/swift/firestore-smoketest/ViewController.swift#L1289-L1296
```

##### Objective-C

**Note:**This product is not available on watchOS and App Clip targets.  

```objective-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);
    }
}];https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/objc/firestore-smoketest-objc/ViewController.m#L1187-L1199
```

### Java

```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());
        }
    }
});https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/DocSnippets.java#L1357-L1370
```

### Kotlin

```kotlin
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())
    }
}https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/kotlin/DocSnippets.kt#L1132-L1142
```

### Dart

```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"),
    );https://github.com/firebase/snippets-flutter/blob/f674af111fe63779c39e79699f7d269231f77563/packages/firebase_snippets_app/lib/snippets/firestore.dart#L880-L884
```

##### Go

    package firestore

    import (
    	"context"
    	"errors"
    	"fmt"
    	"io"

    	"cloud.google.com/go/firestore"
    	firestorepb "cloud.google.com/go/firestore/apiv1/firestorepb"
    )

    func createCountQuery(w io.Writer, projectID string) error {

    	// Instantiate the client
    	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)

    	// `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)
    	if err != nil {
    		return err
    	}

    	count, ok := results["all"]
    	if !ok {
    		return errors.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())
    	return nil
    }  
    https://github.com/GoogleCloudPlatform/golang-samples/blob/2c9f7d4fe3c1b465d5285d558992506b46e78fd7/firestore/aggregate_query_count.go#L16-L61

##### Java

```java
CollectionReference collection = db.collection("cities");
Query query = collection.whereEqualTo("state", "CA");
AggregateQuerySnapshot snapshot = query.count().get().get();
System.out.println("Count: " + snapshot.getCount());
      
```

##### Node.js

```javascript
const collectionRef = db.collection('cities');
const query = collectionRef.where('state', '==', 'CA');
const snapshot = await query.count().get();
console.log(snapshot.data().count);
      
```

##### Python

    from google.cloud import firestore
    from google.cloud.firestore_v1 import aggregation
    from google.cloud.firestore_v1.base_query import FieldFilter


    def create_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 results
        aggregate_query.count(alias="all")

        results = aggregate_query.get()
        for result in results:
            print(f"Alias of results from query: {result[0].alias}")
            print(f"Number of results from query: {result[0].value}")

    https://github.com/GoogleCloudPlatform/python-docs-samples/blob/eff0040dee2bab9c4684f8425aa4d8ef28a9a244/firestore/cloud-client/aggregate_query_count.py#L22-L47

## Use the`sum()`aggregation

Use the`sum()`aggregation to return the total sum of numeric values that match a given query---for example:  

### Web

[Learn more](https://firebase.google.com/docs/web/learn-more#modular-version)about the tree-shakeable Web v9 modular SDK and[upgrade](https://firebase.google.com/docs/web/modular-upgrade)from version 8.  

```javascript
const coll = collection(firestore, 'cities');
const snapshot = await getAggregateFromServer(coll, {
  totalPopulation: sum('population')
});

console.log('totalPopulation: ', snapshot.data().totalPopulation);
    
```

##### Swift

**Note:**This product is not available on watchOS and App Clip targets.  

```swift
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)
}https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/swift/firestore-smoketest/ViewController.swift#L1302-L1309
```

##### Objective-C

**Note:**This product is not available on watchOS and App Clip targets.  

```objective-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"]]);
    }
}];https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/objc/firestore-smoketest-objc/ViewController.m#L1205-L1216
```

### Java

```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());
        }
    }
});https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/DocSnippets.java#L1465-L1478
```

### Kotlin

```kotlin
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())
    }
}https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/kotlin/DocSnippets.kt#L1237-L1247
```

### Dart

```dart
db.collection("cities").aggregate(sum("population")).get().then(
      (res) => print(res.getAverage("population")),
      onError: (e) => print("Error completing: $e"),
    );https://github.com/firebase/snippets-flutter/blob/f674af111fe63779c39e79699f7d269231f77563/packages/firebase_snippets_app/lib/snippets/firestore.dart#L890-L893
```

##### Java

```java
collection = db.collection("cities");
snapshot = collection.aggregate(sum("population")).get().get();
System.out.println("Sum: " + snapshot.get(sum("population")));
      
```

##### Node.js

```javascript
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

```javascript
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}")
      
```

##### Go

```javascript
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
}
      
```

The`sum()`aggregation takes into account any filters on the query and any limit clauses---for example:  

### Web

[Learn more](https://firebase.google.com/docs/web/learn-more#modular-version)about the tree-shakeable Web v9 modular SDK and[upgrade](https://firebase.google.com/docs/web/modular-upgrade)from version 8.  

```javascript
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);
      
```

##### Swift

**Note:**This product is not available on watchOS and App Clip targets.  

```swift
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)
}https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/swift/firestore-smoketest/ViewController.swift#L1315-L1322
```

##### Objective-C

**Note:**This product is not available on watchOS and App Clip targets.  

```objective-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"]]);
    }
}];https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/objc/firestore-smoketest-objc/ViewController.m#L1222-L1234
```

### Java

```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());
        }
    }
});https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/DocSnippets.java#L1484-L1497
```

### Kotlin

```kotlin
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())
    }
}https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/kotlin/DocSnippets.kt#L1253-L1263
```

### Dart

```dart
db
    .collection("cities")
    .where("capital", isEqualTo: true)
    .aggregate(sum("population"))
    .get()
    .then(
      (res) => print(res.getAverage("population")),
      onError: (e) => print("Error completing: $e"),
    );https://github.com/firebase/snippets-flutter/blob/f674af111fe63779c39e79699f7d269231f77563/packages/firebase_snippets_app/lib/snippets/firestore.dart#L899-L907
```

##### Java

```javascript
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

```javascript
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

```javascript
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}")
      
```

##### Go

```javascript
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
}
      
```

## Use the`average()`aggregation

Use the`average()`aggregation to return the average of numeric values that match a given query, for example:  

### Web

[Learn more](https://firebase.google.com/docs/web/learn-more#modular-version)about the tree-shakeable Web v9 modular SDK and[upgrade](https://firebase.google.com/docs/web/modular-upgrade)from version 8.  

```javascript
const coll = collection(firestore, 'cities');
const snapshot = await getAggregateFromServer(coll, {
  averagePopulation: average('population')
});

console.log('averagePopulation: ', snapshot.data().averagePopulation);
    
```

##### Swift

**Note:**This product is not available on watchOS and App Clip targets.  

```swift
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)
}https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/swift/firestore-smoketest/ViewController.swift#L1328-L1335
```

##### Objective-C

**Note:**This product is not available on watchOS and App Clip targets.  

```objective-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"]]);
    }
}];https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/objc/firestore-smoketest-objc/ViewController.m#L1240-L1251
```

### Java

```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());
        }
    }
});https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/DocSnippets.java#L1503-L1516
```

### Kotlin

```kotlin
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())
    }
}https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/kotlin/DocSnippets.kt#L1269-L1279
```

### Dart

```dart
db.collection("cities").aggregate(average("population")).get().then(
      (res) => print(res.getAverage("population")),
      onError: (e) => print("Error completing: $e"),
    );https://github.com/firebase/snippets-flutter/blob/f674af111fe63779c39e79699f7d269231f77563/packages/firebase_snippets_app/lib/snippets/firestore.dart#L913-L916
```

##### Java

```java
collection = db.collection("cities");
snapshot = collection.aggregate(average("population")).get().get();
System.out.println("Average: " + snapshot.get(average("population")));
      
```

##### Node.js

```javascript
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

```javascript
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}")
      
```

##### Go

```javascript
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
}
      
```

The`average()`aggregation takes into account any filters on the query and any limit clauses, for example:  

### Web

[Learn more](https://firebase.google.com/docs/web/learn-more#modular-version)about the tree-shakeable Web v9 modular SDK and[upgrade](https://firebase.google.com/docs/web/modular-upgrade)from version 8.  

```javascript
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);
      
```

##### Swift

**Note:**This product is not available on watchOS and App Clip targets.  

```swift
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)
}https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/swift/firestore-smoketest/ViewController.swift#L1341-L1348
```

##### Objective-C

**Note:**This product is not available on watchOS and App Clip targets.  

```objective-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"]]);
    }
}];https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/objc/firestore-smoketest-objc/ViewController.m#L1257-L1269
```

### Java

```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());
        }
    }
});https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/DocSnippets.java#L1522-L1535
```

### Kotlin

```kotlin
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())
    }
}https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/kotlin/DocSnippets.kt#L1285-L1295
```

### Dart

```dart
db
    .collection("cities")
    .where("capital", isEqualTo: true)
    .aggregate(average("population"))
    .get()
    .then(
      (res) => print(res.getAverage("population")),
      onError: (e) => print("Error completing: $e"),
    );https://github.com/firebase/snippets-flutter/blob/f674af111fe63779c39e79699f7d269231f77563/packages/firebase_snippets_app/lib/snippets/firestore.dart#L922-L930
```

##### Java

```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

```javascript
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

```javascript
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}")
      
```

##### Go

```javascript
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
}
      
```

## Calculate multiple aggregations in a query

You can combine multiple aggregations in a single aggregation pipeline. This can reduce the number of index reads required. If the query includes aggregations on multiple fields, the query might requires a composite index. In that case,Cloud Firestoresuggests an index.

The following example performs multiple aggregations in a single aggregation query:  

### Web

[Learn more](https://firebase.google.com/docs/web/learn-more#modular-version)about the tree-shakeable Web v9 modular SDK and[upgrade](https://firebase.google.com/docs/web/modular-upgrade)from version 8.  

```javascript
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);
      
```

##### Swift

**Note:**This product is not available on watchOS and App Clip targets.  

```swift
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)
}https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/swift/firestore-smoketest/ViewController.swift#L1354-L1366
```

##### Objective-C

**Note:**This product is not available on watchOS and App Clip targets.  

```objective-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"]]);
  }
}];https://github.com/firebase/snippets-ios/blob/6b288cfa45a67c92c5db32953f028f8ed9e5a81b/firestore/objc/firestore-smoketest-objc/ViewController.m#L1275-L1290
```

### Java

```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());
        }
    }
});https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/DocSnippets.java#L1541-L1559
```

### Kotlin

```kotlin
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())
    }
}https://github.com/firebase/snippets-android/blob/294e0edf389e04ad85622081afb988aed37c20fb/firestore/app/src/main/java/com/google/example/firestore/kotlin/DocSnippets.kt#L1301-L1317
```

### Dart

```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"),
);https://github.com/firebase/snippets-flutter/blob/f674af111fe63779c39e79699f7d269231f77563/packages/firebase_snippets_app/lib/snippets/firestore.dart#L936-L951
```

##### Java

```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")));
    
```

##### Node.js

```javascript
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

```javascript
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}")
      
```

##### Go

```javascript
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
  }
}
      
```

Queries with multiple aggregations include only the documents that contain all the fields in each aggregation. This might lead to different results from performing each aggregation separately.

## Security rules for aggregation queries

Cloud FirestoreSecurity Ruleswork the same on aggregation queries as on queries that return documents. In other words, if and only if your rules allow clients to execute certain collection or collection group queries, clients can also perform the aggregation on those queries. Learn more about[howCloud FirestoreSecurity Rulesinteract with queries](https://firebase.google.com/docs/firestore/security/rules-query).

## 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 offline queries. Aggregation queries are only supported through a direct server response. Queries are served only by theCloud Firestorebackend, skipping the local cache and any buffered updates. This behavior is identical to operations that are performed inside[Cloud Firestoretransactions](https://firebase.google.com/docs/firestore/manage-data/transactions).

- If an aggregation can't resolve within 60 seconds, it returns a`DEADLINE_EXCEEDED`error. Performance depends on your index configuration and on the size of the dataset.

  | **Note:** Most queries scale based on the on the size of the result set, not the dataset. However, aggregation queries scale based on the size of the dataset and the number of index entries scanned.

  If the operation can't be completed within the 60 second deadline, a possible workaround is to use[counters](https://firebase.google.com/docs/firestore/solutions/counters)for large datasets.
- Aggregation queries read from index entries and include only indexed fields.

- Adding an`OrderBy`clause to an aggregation query limits the aggregation to the documents where the sorting field exists.

- For`sum()`and`average()`aggregations, non-numeric values are ignored.`sum()`and`average()`aggregations take into account only integer values and floating-point number values.

- When combining multiple aggregations in a single query, note that`sum()`and`average()`ignore non-numeric values while`count()`includes non-numeric values.

- If you combine aggregations that are on different fields, the calculation includes only the documents that contain all those fields.

### Pricing

Pricing for aggregation queries depends on the number of index entries that the query matches. You are charged a small number of reads for a large number of matched entries. You are charged one read operation for each batch of up to 1000 index entries read.

For more information about aggregation queries pricing, see[Aggregation queries](https://firebase.google.com/docs/firestore/pricing#aggregation_queries).