Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Cómo contar documentos con consultas de agregación

Una consulta de agregación procesa los datos de varias entradas de índice para mostrar un solo valor de resumen.

Firestore admite la consulta de agregación count(). count() te permite determinar la cantidad de documentos en una colección o consulta. El servidor calcula el recuento y transmite solo el resultado, un único número entero, a tu app, lo que ahorra en operaciones de lectura de documentos facturados y bytes transferidos, en comparación con la ejecución de la consulta completa.

Las consultas de agregación se basan en la configuración de índices existente que tus consultas ya utilizan, y escalan proporcionalmente a la cantidad de entradas de índice analizadas. Esto significa que las agregaciones de conjuntos de datos pequeños y medianos tienen un rendimiento de 20 a 40 ms, aunque la latencia aumenta con la cantidad de elementos que se cuentan.

Usa la agregación count()

Consulta los datos de ejemplo que configuramos en Cómo obtener datos.

La siguiente agregación count() muestra la cantidad total de ciudades en la colección cities.

Web versión 9

const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
Swift
Nota: Este producto no se encuentra disponible en los destinos de watchOS ni de App Clips.
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
Nota: Este producto no está disponible en los destinos de watchOS ni de 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);
      

La agregación count() toma en cuenta cualquier filtro en la consulta y cualquier cláusula limit. Por ejemplo, la siguiente agregación muestra un recuento de la cantidad de ciudades en las que state es igual a CA.

Web versión 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
Nota: Este producto no se encuentra disponible en los destinos de watchOS ni de App Clips.
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
Nota: Este producto no está disponible en los destinos de watchOS ni de 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);
      

Las reglas de seguridad de Firestore funcionan de la misma manera en las consultas de agregación count() que en las consultas normales que muestran documentos. En otras palabras, solo si tus reglas permiten que los clientes ejecuten determinadas consultas de colecciones o grupos de colecciones, los clientes también pueden realizar la agregación count() en esas consultas. Obtén más información sobre cómo las reglas de seguridad de Firestore interactúan con las consultas.

Limitaciones

Ten en cuenta las siguientes limitaciones en la consulta de agregación count():

  • En la actualidad, las consultas de agregación count() solo se admiten a través de la respuesta directa del servidor. El backend de Firestore entrega las consultas, por lo que se omite la caché local y las actualizaciones almacenadas en búfer. Este comportamiento es idéntico a las operaciones realizadas dentro de las transacciones de Firestore. Por el momento, no puedes usar consultas count() con objetos de escucha en tiempo real ni consultas sin conexión.

  • Si una agregación count() no se puede resolver en 60 segundos, muestra un error DEADLINE_EXCEEDED. El rendimiento depende de la configuración de tu índice y del tamaño del conjunto de datos.

    Si la operación no se puede completar dentro del plazo de 60 segundos, una solución alternativa es usar contadores para conjuntos de datos grandes.

  • La agregación count() lee desde las entradas de índice y cuenta solo los campos indexados.

  • Agregar una cláusula OrderBy a la consulta limita el recuento de las entidades en las que existe la propiedad de ordenamiento.

Precios

El precio de count() depende de la cantidad de entradas de índice que coincidan con la consulta. Se te cobra una pequeña cantidad de lecturas por una gran cantidad de entradas coincidentes.

Consulta la información de precios más detallada.