Est-il possible de compter le nombre d'éléments d'une collection à l'aide de la nouvelle base de données Firebase, Cloud Firestore?
Si oui, comment puis-je faire cela?
firebase
google-cloud-firestore
Guilherme Torres Castro
la source
la source
Réponses:
Mise à jour (avril 2019) - FieldValue.increment (voir grande solution de collecte)
Comme pour de nombreuses questions, la réponse est: cela dépend .
Vous devez être très prudent lorsque vous manipulez de grandes quantités de données sur le front-end. En plus de rendre votre frontal lent, Firestore vous facture également 0,60 USD par million de lectures que vous effectuez.
Petite collection (moins de 100 documents)
À utiliser avec précaution - L'expérience utilisateur frontend peut en prendre un coup
La gestion de cela sur le front-end devrait être correcte tant que vous ne faites pas trop de logique avec ce tableau renvoyé.
Collection moyenne (100 à 1000 documents)
À utiliser avec précaution - Les appels de lecture Firestore peuvent coûter cher
Gérer cela sur le front-end n'est pas faisable car il a trop de potentiel pour ralentir le système des utilisateurs. Nous devons gérer ce côté serveur logique et ne renvoyer que la taille.
L'inconvénient de cette méthode est que vous invoquez toujours des lectures de firestore (égales à la taille de votre collection), qui à long terme peuvent finir par vous coûter plus cher que prévu.
Fonction Cloud:
L'extrémité avant:
Grande collection (plus de 1000 documents)
La solution la plus évolutive
Depuis avril 2019, Firestore permet désormais d'incrémenter les compteurs, de manière complètement atomique, et sans lire les données auparavant . Cela garantit que nous avons des valeurs de compteur correctes même lors de la mise à jour à partir de plusieurs sources simultanément (précédemment résolues à l'aide de transactions), tout en réduisant le nombre de lectures de base de données que nous effectuons.
En écoutant les suppressions ou les créations de documents, nous pouvons ajouter ou supprimer d'un champ de comptage qui se trouve dans la base de données.
Consultez la documentation Firestore - Compteurs distribués ou jetez un œil à l' agrégation de données par Jeff Delaney. Ses guides sont vraiment fantastiques pour quiconque utilise AngularFire, mais ses leçons devraient également être appliquées à d'autres frameworks.
Fonction Cloud:
Maintenant, sur le frontend, vous pouvez simplement interroger ce champ numberOfDocs pour obtenir la taille de la collection.
la source
firestore.runTransaction { ... }
bloc. Cela corrige les problèmes de concurrence d'accèsnumberOfDocs
.Le moyen le plus simple de le faire est de lire la taille d'un "querySnapshot".
Vous pouvez également lire la longueur du tableau docs dans "querySnapshot".
Ou si un "querySnapshot" est vide en lisant la valeur vide, ce qui renverra une valeur booléenne.
la source
db.collection.count()
. Penser à les laisser tomber uniquement pour celaPour autant que je sache, il n'y a pas de solution intégrée pour cela et cela n'est possible que dans le nœud sdk pour le moment. Si tu as un
vous pouvez utiliser
pour définir le champ que vous souhaitez sélectionner. Si vous faites une sélection vide (), vous obtiendrez simplement un tableau de références de document.
exemple:
db.collection('someCollection').select().get().then( (snapshot) => console.log(snapshot.docs.length) );
Cette solution n'est qu'une optimisation pour le pire des cas de téléchargement de tous les documents et ne s'adapte pas aux grandes collections!
Jetez également un œil à ceci:
Comment obtenir un nombre de documents dans une collection avec Cloud Firestore
la source
select(['_id'])
c'est plus rapide queselect()
Soyez prudent en comptant le nombre de documents pour les grandes collections . C'est un peu complexe avec la base de données Firestore si vous voulez avoir un compteur précalculé pour chaque collection.
Un code comme celui-ci ne fonctionne pas dans ce cas:
La raison en est que chaque déclencheur Cloud Firestore doit être idempotent, comme le dit la documentation Firestore: https://firebase.google.com/docs/functions/firestore-events#limitations_and_guarantees
Solution
Ainsi, afin d'éviter plusieurs exécutions de votre code, vous devez gérer les événements et les transactions. C'est ma façon particulière de gérer les grands compteurs de collecte:
Utilisez des cas ici:
Comme vous pouvez le voir, la clé pour empêcher l'exécution multiple est la propriété appelée eventId dans l'objet de contexte. Si la fonction a été gérée plusieurs fois pour le même événement, l'identifiant de l'événement sera le même dans tous les cas. Malheureusement, vous devez avoir une collection «événements» dans votre base de données.
la source
context.eventId
sera toujours le même sur plusieurs invocations du même déclencheur? Dans mes tests, cela semble cohérent, mais je ne trouve aucune documentation «officielle» indiquant cela.En 2020, cela n'est toujours pas disponible dans le SDK Firebase, mais il est disponible dans les extensions Firebase (bêta), mais c'est assez complexe à configurer et à utiliser ...
Une approche raisonnable
Helpers ... (créer / supprimer semble redondant mais est moins cher que onUpdate)
Crochets Firestore exportés
En action
La collection racine du bâtiment et toutes les sous-collections seront suivies.
Ici sous le
/counters/
chemin racineDésormais, le décompte des collections sera mis à jour automatiquement et éventuellement! Si vous avez besoin d'un décompte, utilisez simplement le chemin de la collection et ajoutez-lui le préfixe
counters
.la source
Je suis d'accord avec @Matthew, cela coûtera cher si vous effectuez une telle requête.
[CONSEILS AUX DÉVELOPPEURS AVANT DE DÉMARRER LEURS PROJETS]
Puisque nous avons prévu cette situation au début, nous pouvons en fait faire une collection à savoir des compteurs avec un document pour stocker tous les compteurs dans un champ de type
number
.Par exemple:
Pour chaque opération CRUD sur la collection, mettez à jour le document compteur:
La prochaine fois, lorsque vous souhaitez obtenir le nombre de collections, il vous suffit d'interroger / pointer sur le champ du document. [1 opération de lecture]
De plus, vous pouvez stocker le nom des collections dans un tableau, mais ce sera délicat, la condition du tableau dans firebase est indiquée ci-dessous:
Donc, si vous n'allez pas supprimer la collection, vous pouvez en fait utiliser un tableau pour stocker la liste des noms de collections au lieu d'interroger toute la collection à chaque fois.
J'espère que ça aide!
la source
Non, il n'y a pas de support intégré pour les requêtes d'agrégation pour le moment. Cependant, vous pouvez faire certaines choses.
Le premier est documenté ici . Vous pouvez utiliser des transactions ou des fonctions cloud pour gérer des informations agrégées:
Cet exemple montre comment utiliser une fonction pour suivre le nombre de notes dans une sous-collection, ainsi que la note moyenne.
La solution mentionnée par jbb est également utile si vous ne souhaitez compter que rarement les documents. Assurez-vous d'utiliser l'
select()
instruction pour éviter de télécharger la totalité de chaque document (c'est beaucoup de bande passante lorsque vous n'avez besoin que d'un décompte).select()
n'est disponible que dans les SDK du serveur pour le moment afin que la solution ne fonctionne pas dans une application mobile.la source
Il n'y a pas d'option directe disponible. Tu ne peux pas faire
db.collection("CollectionName").count()
. Vous trouverez ci-dessous les deux façons dont vous pouvez trouver le nombre de documents dans une collection.1: - Obtenez tous les documents de la collection, puis obtenez leur taille (ce n'est pas la meilleure solution)
En utilisant le code ci-dessus, vos lectures de document seront égales à la taille des documents dans une collection et c'est la raison pour laquelle il faut éviter d'utiliser la solution ci-dessus.
2: - Créez un document séparé avec dans votre collection qui stockera le nombre de documents dans la collection. (Meilleure solution)
Ci-dessus, nous avons créé un document avec le nombre de noms pour stocker toutes les informations de comptage.Vous pouvez mettre à jour le document de comptage de la manière suivante: -
Wrt price (Document Read = 1) et récupération rapide des données, la solution ci-dessus est bonne.
la source
Incrémentez un compteur en utilisant admin.firestore.FieldValue.increment :
Dans cet exemple, nous incrémentons un
instanceCount
champ dans le projet chaque fois qu'un document est ajouté à lainstances
sous-collection. Si le champ n'existe pas encore, il sera créé et incrémenté à 1.L'incrémentation est transactionnelle en interne, mais vous devez utiliser un compteur distribué si vous devez incrémenter plus fréquemment que toutes les 1 seconde.
Il est souvent préférable de mettre en œuvre
onCreate
etonDelete
plutôt queonWrite
de demanderonWrite
des mises à jour, ce qui signifie que vous dépensez plus d'argent pour des appels de fonctions inutiles (si vous mettez à jour les documents de votre collection).la source
Une solution de contournement consiste à:
écrire un compteur dans un document Firebase, que vous incrémentez dans une transaction à chaque fois que vous créez une nouvelle entrée
Vous stockez le décompte dans un champ de votre nouvelle entrée (ex: position: 4).
Ensuite, vous créez un index sur ce champ (position DESC).
Vous pouvez faire un saut + limite avec une requête.Where ("position", "<" x) .OrderBy ("position", DESC)
J'espère que cela t'aides!
la source
J'ai créé une fonction universelle utilisant toutes ces idées pour gérer toutes les situations de compteur (sauf les requêtes).
Cela gère les événements, les incréments et les transactions. La beauté de ceci, c'est que si vous n'êtes pas sûr de l'exactitude d'un document (probablement pendant qu'il est encore en version bêta), vous pouvez supprimer le compteur pour qu'il les additionne automatiquement au prochain déclencheur. Oui, cela coûte, alors ne le supprimez pas autrement.
Même genre de chose pour obtenir le décompte:
Vous pouvez également créer une tâche cron (fonction planifiée) pour supprimer les anciens événements afin d'économiser de l'argent sur le stockage de la base de données. Vous avez besoin d'au moins un plan Blaze, et il peut y avoir plus de configuration. Vous pouvez l'exécuter tous les dimanches à 23 heures, par exemple. https://firebase.google.com/docs/functions/schedule-functions
Ceci n'est pas testé , mais devrait fonctionner avec quelques ajustements:
Enfin, n'oubliez pas de protéger les collections dans firestore.rules :
Mise à jour: requêtes
En ajoutant à mon autre réponse si vous souhaitez également automatiser le nombre de requêtes, vous pouvez utiliser ce code modifié dans votre fonction cloud:
Ce qui mettra automatiquement à jour le postsCount dans le userDocument. Vous pouvez facilement en ajouter un autre à de nombreux comptes de cette façon. Cela vous donne simplement des idées sur la façon dont vous pouvez automatiser les choses. Je vous ai également donné un autre moyen de supprimer les événements. Vous devez lire chaque date pour la supprimer, donc cela ne vous évitera pas vraiment de les supprimer plus tard, cela ralentit simplement la fonction.
la source
Il m'a fallu un certain temps pour que cela fonctionne en fonction de certaines des réponses ci-dessus, alors j'ai pensé que je le partagerais pour que d'autres puissent l'utiliser. J'espère que c'est utile.
la source
J'ai beaucoup essayé avec différentes approches. Et enfin, j'améliore une des méthodes. Vous devez d'abord créer une collection séparée et y enregistrer tous les événements. Deuxièmement, vous devez créer un nouveau lambda qui sera déclenché par le temps. Ce lambda comptera les événements dans la collection d'événements et effacera les documents d'événements. Détails du code dans l'article. https://medium.com/@ihor.malaniuk/how-to-count-documents-in-google-cloud-firestore-b0e65863aeca
la source
Cette requête aboutira au nombre de documents.
la source
Cela utilise le comptage pour créer un identifiant numérique unique. Dans mon utilisation, je ne décrémenterai jamais , même si
document
l'ID pour lequel l'ID est nécessaire est supprimé.Sur une
collection
création qui a besoin d'une valeur numérique uniqueappData
avec un document,set
avec.doc
identifiantonly
uniqueNumericIDAmount
sur 0 dans lefirebase firestore console
doc.data().uniqueNumericIDAmount + 1
comme identifiant numérique uniqueappData
collectionuniqueNumericIDAmount
avecfirebase.firestore.FieldValue.increment(1)
la source
la source