Catch up on highlights from Firebase at Google I/O 2023. Learn more

Policz dokumenty za pomocą zapytań agregujących

Zapytanie agregujące przetwarza dane z wielu wpisów indeksu w celu zwrócenia pojedynczej wartości podsumowania.

Cloud Firestore obsługuje zapytanie agregujące count() . count() pozwala określić liczbę dokumentów w kolekcji lub zapytaniu. Serwer oblicza liczbę i przesyła tylko wynik, pojedynczą liczbę całkowitą, z powrotem do Twojej aplikacji, oszczędzając zarówno na odczytach rozliczonych dokumentów, jak i przesłanych bajtach w porównaniu z wykonaniem pełnego zapytania.

Zapytania agregujące opierają się na istniejącej konfiguracji indeksu, z której już korzystają Twoje zapytania, i są skalowane proporcjonalnie do liczby przeskanowanych wpisów indeksu. Oznacza to, że agregacje małych i średnich zestawów danych działają w ciągu 20-40 ms, chociaż opóźnienie wzrasta wraz z liczbą zliczonych elementów.

Użyj agregacji count()

Zapoznaj się z przykładowymi danymi, które skonfigurowaliśmy w sekcji Pobieranie danych .

Poniższa agregacja count() zwraca całkowitą liczbę miast w kolekcji cities .

Web modular API

const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
Szybki
Uwaga: ten produkt nie jest dostępny w docelowych systemach watchOS i App Clip.
let query = db.collection("cities")
let countQuery = query.count
do {
    let snapshot = try await countQuery.getAggregation(source: .server)
    print(snapshot.count)
} catch {
    print(error)
}
Cel C
Uwaga: ten produkt nie jest dostępny w docelowych systemach watchOS i App Clip.
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"),
    );
Jawa
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);
      

Agregacja count() uwzględnia wszelkie filtry w zapytaniu i wszelkie klauzule limit . Na przykład poniższa agregacja zwraca liczbę miast, w których state jest równy CA .

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);
Szybki
Uwaga: ten produkt nie jest dostępny w docelowych systemach watchOS i App Clip.
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)
}
Cel C
Uwaga: ten produkt nie jest dostępny w docelowych systemach watchOS i App Clip.
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"),
    );
Jawa
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);
      

Reguły bezpieczeństwa Cloud Firestore działają tak samo w przypadku zapytań agregujących count() , jak w przypadku zwykłych zapytań zwracających dokumenty. Innymi słowy, wtedy i tylko wtedy, gdy Twoje reguły zezwalają klientom na wykonywanie określonych zapytań kolekcji lub grup kolekcji, klienci mogą również wykonywać agregację count() dla tych zapytań. Dowiedz się więcej o interakcji zasad bezpieczeństwa Cloud Firestore z zapytaniami .

Ograniczenia

Zwróć uwagę na następujące ograniczenia kwerendy agregującej count() :

  • zapytania agregujące count() są obecnie obsługiwane tylko przez bezpośrednią odpowiedź serwera. Zapytania są obsługiwane tylko przez backend Cloud Firestore, pomijając lokalną pamięć podręczną i wszelkie buforowane aktualizacje. To zachowanie jest identyczne z operacjami wykonywanymi w ramach transakcji Cloud Firestore . Obecnie nie można używać zapytań count() z odbiornikami działającymi w czasie rzeczywistym i zapytaniami offline.

  • Jeśli agregacja count() nie może rozwiązać problemu w ciągu 60 sekund, zwraca błąd DEADLINE_EXCEEDED . Wydajność zależy od konfiguracji indeksu i rozmiaru zestawu danych.

    Jeśli operacja nie może zostać zakończona w ciągu 60 sekund, możliwym obejściem jest użycie liczników dla dużych zestawów danych.

  • Agregacja count() odczytuje z pozycji indeksu i zlicza tylko pola indeksowane.

  • Dodanie klauzuli OrderBy do zapytania ogranicza zliczanie do dokumentów, w których istnieje pole sortowania.

cennik

Cena funkcji count() zależy od liczby wpisów indeksu pasujących do zapytania. Za dużą liczbę pasujących wpisów pobierana jest opłata za niewielką liczbę odczytów.

Zobacz bardziej szczegółowe informacje o cenach .