Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Compter des documents avec des requêtes d'agrégation

Une requête d'agrégation traite les données de plusieurs entrées d'index pour renvoyer une seule valeur récapitulative.

Firestore accepte la requête d'agrégation count(). count() permet de déterminer le nombre de documents dans une collection ou une requête. Le serveur calcule le nombre de résultats et ne transmet à l'application que le résultat, un entier entier, ce qui permet d'économiser à la fois les lectures de documents facturés et les octets transférés, par rapport à l'exécution de la requête complète.

Les requêtes d'agrégation s'appuient sur la configuration d'index existante que vos requêtes utilisent déjà et s'adaptent proportionnellement au nombre d'entrées d'index analysées. Cela signifie que les agrégations d'ensembles de données de petite taille ou de taille moyenne sont effectuées en 20 à 40 ms, bien que la latence augmente en fonction du nombre d'éléments comptabilisés.

Utiliser l'agrégation count()

Consultez les exemples de données que nous avons configurés dans Obtenir des données.

L'agrégation count() suivante renvoie le nombre total de villes dans la collection cities.

Version Web 9

const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
Swift
Remarque : Ce produit n'est pas disponible sur les cibles watchOS et 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);
}
Objective-C
Remarque : Ce produit n'est pas disponible sur les cibles watchOS et 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
Android
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
Android
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
Android
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);
      

L'agrégation count() prend en compte tous les filtres de la requête et toutes les clauses limit. Par exemple, l'agrégation suivante renvoie le nombre de villes dans lesquelles state est égal à CA.

Version Web 9

const coll = collection(db, "cities");
const q = query(coll, where("state", "==", "CA"));
const snapshot = await getCountFromServer(q);
console.log('count: ', snapshot.data().count);
Swift
Remarque : Ce produit n'est pas disponible sur les cibles watchOS et 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);
}
Objective-C
Remarque : Ce produit n'est pas disponible sur les cibles watchOS et 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
Android
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
Android
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
Android
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);
      

Les règles de sécurité Firestore fonctionnent de la même manière pour les requêtes d'agrégation count() et pour les requêtes standards qui renvoient des documents. En d'autres termes, si et seulement si vos règles autorisent les clients à exécuter certaines requêtes de collection ou de groupe de collections, les clients peuvent également effectuer l'agrégation count() sur ces requêtes. Découvrez comment les règles de sécurité Firestore interagissent avec les requêtes.

Limites

Notez les limitations suivantes sur la requête d'agrégation count():

  • Les requêtes d'agrégation count() ne sont actuellement acceptées que via la réponse directe du serveur. Les requêtes ne sont diffusées que par le backend Firestore, en ignorant le cache local et les mises à jour en mémoire tampon. Ce comportement est identique aux opérations effectuées dans les transactions Firestore. Actuellement, vous ne pouvez pas utiliser de requêtes count() avec des écouteurs en temps réel et des requêtes hors connexion.

  • Si une agrégation count() ne peut pas être résolue dans les 60 secondes, elle renvoie une erreur DEADLINE_EXCEEDED. Les performances dépendent de la configuration de votre index et de la taille de l'ensemble de données.

    Si l'opération ne peut pas être terminée dans le délai de 60 secondes, une solution de contournement possible consiste à utiliser des compteurs pour les grands ensembles de données.

  • L'agrégation count() lit les entrées d'index et ne compte que les champs indexés.

  • L'ajout d'une clause OrderBy à la requête limite le nombre d'entités où la propriété de tri existe.

Tarifs

La tarification de count() dépend du nombre d'entrées d'index correspondant à la requête. Vous êtes facturé pour un petit nombre de lectures pour un grand nombre d'entrées correspondantes.

Pour obtenir des informations tarifaires plus détaillées, cliquez ici.