Firebase is back at Google I/O on May 10! Register now

Zählen Sie Dokumente mit Aggregationsabfragen

Mit Sammlungen den Überblick behalten Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.

Eine Aggregationsabfrage verarbeitet die Daten aus mehreren Indexeinträgen, um einen einzelnen Zusammenfassungswert zurückzugeben.

Cloud Firestore unterstützt die Aggregationsabfrage count() . count() ermöglicht es Ihnen, die Anzahl der Dokumente in einer Sammlung oder Abfrage zu bestimmen. Der Server berechnet die Anzahl und überträgt nur das Ergebnis, eine einzelne Ganzzahl, zurück an Ihre App, wodurch im Vergleich zur Ausführung der vollständigen Abfrage sowohl Lesevorgänge für abgerechnete Dokumente als auch übertragene Bytes eingespart werden.

Aggregationsabfragen basieren auf der vorhandenen Indexkonfiguration, die Ihre Abfragen bereits verwenden, und skalieren proportional zur Anzahl der gescannten Indexeinträge. Das bedeutet, dass Aggregationen von kleinen bis mittelgroßen Datensätzen innerhalb von 20–40 ms ausgeführt werden, obwohl die Latenz mit der Anzahl der gezählten Elemente zunimmt.

Verwenden Sie die count() -Aggregation

Sehen Sie sich die Beispieldaten an, die wir in Daten abrufen eingerichtet haben.

Die folgende count() -Aggregation gibt die Gesamtzahl der Städte in der cities zurück.

Web version 9

const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
Schnell
Hinweis: Dieses Produkt ist auf watchOS- und App Clip-Zielen nicht verfügbar.
let query = db.collection("cities")
let countQuery = query.count
do {
    let snapshot = try await countQuery.getAggregation(source: .server)
    print(snapshot.count)
} catch {
    print(error);
}
Ziel c
Hinweis: Dieses Produkt ist auf watchOS- und App Clip-Zielen nicht verfügbar.
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())
    }
}

Java

CollectionReference collection = db.collection("cities");
AggregateQuery countQuery = collection.count();
countQuery.get(AggregateSource.SERVER).addOnCompleteListener(task -> {
  if (task.isSuccessful()) {
    AggregateQuerySnapshot snapshot = task.getResult();
    Log.d(TAG, "Count: " + snapshot.getCount());
  } else {
    Log.d(TAG, "Count failed: ", task.getException());
  }
});
      
Java
CollectionReference collection = db.collection("cities");
AggregateQuerySnapshot snapshot = collection.count().get().get();
System.out.println("Count: " + snapshot.getCount());
      
Node.js
const collectionRef = db.collection('cities');
const snapshot = await collectionRef.count().get();
console.log(snapshot.data().count);
      

Die count() Aggregation berücksichtigt alle Filter für die Abfrage und alle limit . Die folgende Aggregation gibt beispielsweise die Anzahl der Städte zurück, in denen state gleich CA ist.

Web version 9

const coll = collection(db, "cities");
const q = query(coll, where("state", "==", "CA"));
const snapshot = await getCountFromServer(q);
console.log('count: ', snapshot.data().count);
Schnell
Hinweis: Dieses Produkt ist auf watchOS- und App Clip-Zielen nicht verfügbar.
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);
}
Ziel c
Hinweis: Dieses Produkt ist auf watchOS- und App Clip-Zielen nicht verfügbar.
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())
    }
}

Java

CollectionReference collection = db.collection("cities");
Query query = collection.whereEqualTo("state", "CA");
AggregateQuery countQuery = query.count();
countQuery.get(AggregateSource.SERVER).addOnCompleteListener(task -> {
  if (task.isSuccessful()) {
    AggregateQuerySnapshot snapshot = task.getResult();
    Log.d(TAG, "Count: " + snapshot.getCount());
  } else {
    Log.d(TAG, "Count failed: ", task.getException());
  }
});
      
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
const collectionRef = db.collection('cities');
const query = collectionRef.where('state', '==', 'CA');
const snapshot = await query.count().get();
console.log(snapshot.data().count);
      

Cloud Firestore-Sicherheitsregeln funktionieren bei count() Aggregationsabfragen genauso wie bei normalen Abfragen, die Dokumente zurückgeben. Mit anderen Worten, wenn und nur wenn Ihre Regeln Clients erlauben, bestimmte Sammlungs- oder Sammlungsgruppenabfragen auszuführen, können Clients auch die count() Aggregation für diese Abfragen durchführen. Erfahren Sie mehr darüber, wie Cloud Firestore-Sicherheitsregeln mit Abfragen interagieren .

Einschränkungen

Beachten Sie die folgenden Einschränkungen bei der Aggregationsabfrage count() :

  • count() Aggregationsabfragen werden derzeit nur über Direct Server Response unterstützt. Abfragen werden nur vom Cloud Firestore-Back-End bedient, wobei der lokale Cache und alle gepufferten Aktualisierungen übersprungen werden. Dieses Verhalten ist identisch mit Vorgängen, die innerhalb von Cloud Firestore-Transaktionen durchgeführt werden. Sie können derzeit keine count() Abfragen mit Echtzeit-Listenern und Offline-Abfragen verwenden.

  • Wenn eine count() Aggregation nicht innerhalb von 60 Sekunden aufgelöst werden kann, gibt sie einen DEADLINE_EXCEEDED Fehler zurück. Die Leistung hängt von Ihrer Indexkonfiguration und der Größe des Datasets ab.

    Wenn der Vorgang nicht innerhalb der 60-Sekunden-Frist abgeschlossen werden kann, besteht eine mögliche Problemumgehung darin, Zähler für große Datensätze zu verwenden.

  • Die Aggregation count() liest aus Indexeinträgen und zählt nur indizierte Felder.

  • Durch Hinzufügen einer OrderBy Klausel zur Abfrage wird die Anzahl auf die Entitäten begrenzt, in denen die Sortiereigenschaft vorhanden ist.

Preisgestaltung

Die Preise für count() hängen von der Anzahl der Indexeinträge ab, die mit der Abfrage übereinstimmen. Ihnen wird eine kleine Anzahl von Lesevorgängen für eine große Anzahl übereinstimmender Einträge in Rechnung gestellt.

Siehe detailliertere Preisinformationen .