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
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
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
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
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 consultascount()
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 errorDEADLINE_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.