¿Es posible contar cuántos elementos tiene una colección usando la nueva base de datos Firebase, Cloud Firestore?
Si es así, ¿cómo hago eso?
firebase
google-cloud-firestore
Guilherme Torres Castro
fuente
fuente
Respuestas:
Actualización (abril de 2019) - FieldValue.increment (ver solución de colección grande)
Como con muchas preguntas, la respuesta es: depende .
Debe tener mucho cuidado al manejar grandes cantidades de datos en el front-end. Además de hacer que su front-end se sienta lento, Firestore también le cobra $ 0.60 por millón de lecturas que realiza.
Colección pequeña (menos de 100 documentos)
Úselo con cuidado: la experiencia del usuario frontend puede verse afectada
Manejar esto en el front end debería estar bien siempre que no esté haciendo demasiada lógica con esta matriz devuelta.
Colección mediana (100 a 1000 documentos)
Úselo con cuidado: las invocaciones de lectura de Firestore pueden costar mucho
Manejar esto en el front end no es factible ya que tiene demasiado potencial para ralentizar el sistema de los usuarios. Deberíamos manejar este lado del servidor lógico y solo devolver el tamaño.
El inconveniente de este método es que todavía está invocando lecturas de almacén de incendios (igual al tamaño de su colección), que a la larga puede terminar costándole más de lo esperado.
Función de la nube:
Interfaz:
Gran colección (más de 1000 documentos)
La solución más escalable
A partir de abril de 2019, Firestore ahora permite incrementar los contadores, de forma completamente atómica, y sin leer los datos antes . Esto garantiza que tengamos los valores de contador correctos incluso cuando se actualizan desde múltiples fuentes simultáneamente (previamente resueltas mediante transacciones), al tiempo que se reduce la cantidad de lecturas de bases de datos que realizamos.
Al escuchar cualquier documento eliminado o creado, podemos agregar o eliminar de un campo de recuento que se encuentra en la base de datos.
Vea los documentos de la tienda de incendios: contadores distribuidos o eche un vistazo a la agregación de datos por Jeff Delaney. Sus guías son realmente fantásticas para cualquiera que use AngularFire, pero sus lecciones también deberían trasladarse a otros marcos.
Función de la nube:
Ahora en la interfaz puede consultar este campo numberOfDocs para obtener el tamaño de la colección.
fuente
firestore.runTransaction { ... }
bloque. Esto soluciona problemas de concurrencia con el accesonumberOfDocs
.La forma más sencilla de hacerlo es leer el tamaño de una "consulta instantánea".
También puede leer la longitud de la matriz de documentos dentro de "querySnapshot".
O si un "querySnapshot" está vacío leyendo el valor vacío, que devolverá un valor booleano.
fuente
db.collection.count()
. Pensando en dejarlos solo por estoHasta donde sé, no hay una solución integrada para esto y solo es posible en el nodo sdk en este momento. Si tienes un
puedes usar
para definir qué campo desea seleccionar. Si hace una selección vacía (), solo obtendrá una matriz de referencias de documentos.
ejemplo:
db.collection('someCollection').select().get().then( (snapshot) => console.log(snapshot.docs.length) );
¡Esta solución es solo una optimización para el peor de los casos de descarga de todos los documentos y no se escala en grandes colecciones!
También eche un vistazo a esto:
Cómo obtener un recuento de la cantidad de documentos en una colección con Cloud Firestore
fuente
select(['_id'])
es más rápido queselect()
Tenga cuidado al contar el número de documentos para grandes colecciones . Es un poco complejo con la base de datos de firestore si desea tener un contador precalculado para cada colección.
Un código como este no funciona en este caso:
La razón es porque cada desencadenante del almacén de incendios en la nube debe ser idempotente, como dice la documentación del almacén de incendios: https://firebase.google.com/docs/functions/firestore-events#limitations_and_guarantees
Solución
Por lo tanto, para evitar múltiples ejecuciones de su código, debe administrar eventos y transacciones. Esta es mi forma particular de manejar grandes contadores de colección:
Use los casos aquí:
Como puede ver, la clave para evitar la ejecución múltiple es la propiedad llamada eventId en el objeto de contexto. Si la función se ha manejado muchas veces para el mismo evento, la identificación del evento será la misma en todos los casos. Desafortunadamente, debe tener una colección de "eventos" en su base de datos.
fuente
context.eventId
siempre será igual en múltiples invocaciones del mismo activador? En mis pruebas parece ser consistente, pero no puedo encontrar ninguna documentación "oficial" que indique esto.En 2020, esto todavía no está disponible en Firebase SDK; sin embargo, está disponible en Firebase Extensions (Beta); sin embargo, es bastante complejo de configurar y usar ...
Un enfoque razonable
Ayudantes ... (crear / eliminar parece redundante pero es más barato que onUpdate)
Ganchos exportados de Firestore
En acción
Se rastreará la colección raíz del edificio y todas las subcolecciones .
Aquí debajo de la
/counters/
ruta raíz¡Ahora los recuentos de colecciones se actualizarán automáticamente y eventualmente! Si necesita un recuento, simplemente use la ruta de recopilación y agregue el prefijo
counters
.fuente
Estoy de acuerdo con @Matthew, costará mucho si realiza dicha consulta.
[CONSEJO PARA DESARROLLADORES ANTES DE COMENZAR SUS PROYECTOS]
Como hemos previsto esta situación al principio, podemos hacer una colección, a saber, contadores con un documento para almacenar todos los contadores en un campo con tipo
number
.Por ejemplo:
Para cada operación CRUD en la colección, actualice el documento de contador:
La próxima vez, cuando desee obtener el número de recopilación, solo necesita consultar / señalar el campo del documento. [1 operación de lectura]
Además, puede almacenar el nombre de las colecciones en una matriz, pero esto será complicado, la condición de la matriz en firebase se muestra a continuación:
Entonces, si no va a eliminar la colección, en realidad puede usar la matriz para almacenar la lista de nombres de colecciones en lugar de consultar toda la colección cada vez.
¡Espero eso ayude!
fuente
No, en este momento no hay soporte incorporado para consultas de agregación. Sin embargo, hay algunas cosas que podrías hacer.
El primero está documentado aquí . Puede usar transacciones o funciones en la nube para mantener información agregada:
Este ejemplo muestra cómo usar una función para realizar un seguimiento del número de calificaciones en una subcolección, así como la calificación promedio.
La solución que mencionó jbb también es útil si solo desea contar documentos con poca frecuencia. Asegúrese de usar la
select()
declaración para evitar descargar todos los documentos (eso es mucho ancho de banda cuando solo necesita un recuento).select()
por ahora solo está disponible en los SDK del servidor, por lo que la solución no funcionará en una aplicación móvil.fuente
No hay una opción directa disponible. Usted cant't haces
db.collection("CollectionName").count()
. A continuación se muestran las dos formas en que puede encontrar el recuento de la cantidad de documentos dentro de una colección.1: - Obtenga todos los documentos de la colección y luego obtenga su tamaño. (No es la mejor solución)
Al usar el código anterior, las lecturas de sus documentos serán iguales al tamaño de los documentos dentro de una colección y esa es la razón por la cual uno debe evitar el uso de la solución anterior.
2: - Cree un documento separado con en su colección que almacenará la cantidad de documentos en la colección. (La mejor solución)
Arriba creamos un documento con recuentos de nombres para almacenar toda la información de recuento. Puede actualizar el documento de recuento de la siguiente manera: -
wrt price (Document Read = 1) y recuperación rápida de datos, la solución anterior es buena.
fuente
Incremente un contador usando admin.firestore.FieldValue.increment :
En este ejemplo, incrementamos un
instanceCount
campo en el proyecto cada vez que se agrega un documento a lainstances
subcolección. Si el campo aún no existe, se creará e incrementará a 1.El incremento es transaccional internamente, pero debe usar un contador distribuido si necesita incrementar con más frecuencia que cada 1 segundo.
A menudo es preferible implementarlo
onCreate
y enonDelete
lugar de hacerloonWrite
, solicitaráonWrite
actualizaciones, lo que significa que está gastando más dinero en invocaciones de funciones innecesarias (si actualiza los documentos de su colección).fuente
Una solución alternativa es:
escribe un contador en un documento de Firebase, que incrementa dentro de una transacción cada vez que crea una nueva entrada
Almacena el recuento en un campo de su nueva entrada (es decir: posición: 4).
Luego crea un índice en ese campo (posición DESC).
Puede hacer un salto + límite con una consulta. Donde ("posición", "<" x) .OrderBy ("posición", DESC)
¡Espero que esto ayude!
fuente
Creé una función universal usando todas estas ideas para manejar todas las situaciones de contador (excepto las consultas).
Esto maneja eventos, incrementos y transacciones. Lo bueno de esto es que si no está seguro de la precisión de un documento (probablemente mientras esté en versión beta), puede eliminar el contador para que se agregue automáticamente en el siguiente activador. Sí, esto cuesta, así que no lo elimine de otra manera.
El mismo tipo de cosas para obtener el recuento:
Además, puede crear un trabajo cron (función programada) para eliminar eventos antiguos y ahorrar dinero en el almacenamiento de la base de datos. Necesita al menos un plan de incendio, y puede haber alguna configuración más. Puede ejecutarlo todos los domingos a las 11 p.m., por ejemplo. https://firebase.google.com/docs/functions/schedule-functions
Esto no se ha probado , pero debería funcionar con algunos ajustes:
Y por último, no olvide proteger las colecciones en firestore.rules :
Actualización: consultas
Agregando a mi otra respuesta si también desea automatizar el conteo de consultas, puede usar este código modificado en su función en la nube:
Lo que actualizará automáticamente el postsCount en el userDocument. Podría agregar fácilmente otro a muchos recuentos de esta manera. Esto solo te da ideas de cómo puedes automatizar las cosas. También te di otra forma de eliminar los eventos. Debe leer cada fecha para eliminarla, por lo que realmente no le ahorrará eliminarlas más tarde, solo hace que la función sea más lenta.
fuente
Me tomó un tiempo hacer que esto funcionara en base a algunas de las respuestas anteriores, así que pensé en compartirlo para que otros lo usen. Espero que sea útil.
fuente
He intentado mucho con diferentes enfoques. Y finalmente, mejoro uno de los métodos. Primero debe crear una colección separada y guardar allí todos los eventos. En segundo lugar, debe crear una nueva lambda que se activará con el tiempo. Esta lambda contará eventos en la colección de eventos y borrará documentos de eventos. Detalles del código en el artículo. https://medium.com/@ihor.malaniuk/how-to-count-documents-in-google-cloud-firestore-b0e65863aeca
fuente
Esta consulta dará como resultado el recuento de documentos.
fuente
Esto usa el conteo para crear una identificación numérica única. En mi uso, no volveré a disminuir nunca , incluso cuando
document
se elimine la identificación necesaria.Sobre una
collection
creación que necesita un valor numérico únicoappData
con un documento,set
con.doc
identificaciónonly
uniqueNumericIDAmount
a 0 en elfirebase firestore console
doc.data().uniqueNumericIDAmount + 1
como la identificación numérica únicaappData
colecciónuniqueNumericIDAmount
confirebase.firestore.FieldValue.increment(1)
fuente
fuente