Pourquoi compter le nombre de documents dans une collection Firebase ?
Dans une application Flutter, il peut parfois être utile de connaître le nombre de documents présents dans une collection Firebase. Par exemple, si vous souhaitez sélectionner un document au hasard, vous devez d’abord connaître la taille de la liste des documents pour définir un intervalle.
Faire cela est relativement simple si le nombre de documents reste inchangé d’un jour à l’autre, mais comment faire si celui-ci évolue ? Vous ne pourrez pas utiliser un intervalle fixe et le changer à la main à chaque ajout de document, peut vite devenir chronophage et vous faire perdre un temps précieux. Une autre solution serait de compter les documents dans votre liste lors de chaque requête. Mais ceci peut se révéler non seulement long et coûteux en termes de temps d’exécution, mais également plus onéreux. En effet, vous devrez lire chaque document de la liste pour pouvoir les compter, or chaque lecture Firebase vous est facturée.
Une solution optimale consiste donc à utiliser une Cloud Function pour calculer le nombre de documents de vos listes en back-end, puis stocker cette information dans un emplacement facilement accessible par votre application.
Compter les documents à interval fixe
Une première manière d’implementer une fonction cloud qui va compter vos documents est de la déclencher à intervalles fixes, par exemple toutes les 24 heures.
Voici donc une manière très simple de mettre en place une fonction planifiée pour compter le nombre de documents dans une collection Firebase :
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
exports.countDocumentsScheduled = functions.pubsub.schedule("every 24 hours").onRun(async (context) => {
try {
const collectionName = "your_collection_name"; // Remplacez par le nom de votre collection
// Récupérez tous les documents de la collection
const docsSnapshot = await db.collection(collectionName).get();
// Comptez les documents
const count = docsSnapshot.size;
// Enregistrez le résultat dans un document spécifique
await db.collection("metadata").doc("documentCount").set({
count: count,
lastUpdated: admin.firestore.FieldValue.serverTimestamp()
});
console.log("Nombre de documents dans ${collectionName} : ${count}");
} catch (error) {
console.error("Erreur lors du comptage des documents :", error);
}
});
Toutes les 24 heures, à partir du moment où la fonction a été déployée, cloud function va passer à travers votre collection pour compter le nombre de documents dans la collection que vous avez définie. Le résultat va ensuite être stocké dans le document que vous avez défini.
Il existe bien d’autres timestamps que vous pouvez planifier pour déclencher votre fonction. Par exemple :
every 1 hours
: Toutes les heures ;every 30 minutes
: Toutes les 30 minutes ;2:00
: Tous les jours à 2h du matin ;every monday 09:00
: Tous les lundis à 9h du matin ;1 of month 00:00
: Tous les mois, le 1ᵉʳ à 0h ;every weekday 18:00
: Tous les jours de semaine à 18h, etc.
Appeler la fonction de comptage depuis Flutter
Une autre manière de déclencher votre fonction, est de l’appeler lorsque l’utilisateur clique sur un bouton dans votre application Flutter.
Voici comment la mettre en place :
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
exports.countDocumentsOnRequest = functions.https.onRequest(async (req, res) => {
try {
const collectionName = req.query.collectionName || "your_collection_name"; // Changez par le nom de votre collection
// Vérifiez que la méthode est une requête GET
if (req.method !== "GET") {
return res.status(405).send("Méthode non autorisée. Utilisez une requête GET.");
}
// Récupérez tous les documents de la collection
const docsSnapshot = await db.collection(collectionName).get();
// Comptez les documents
const count = docsSnapshot.size;
// Enregistrez le résultat dans un document spécifique
await db.collection("metadata").doc("documentCount").set({
count: count,
lastUpdated: admin.firestore.FieldValue.serverTimestamp(),
});
console.log(`Nombre de documents dans ${collectionName} : ${count}`);
// Répondez avec le compte des documents
res.status(200).json({count});
} catch (error) {
console.error("Erreur lors du comptage des documents :", error);
res.status(500).send("Erreur interne du serveur.");
}
});
À chaque fois que l’utilisateur va appeler cette fonction depuis l’interface de l’application Flutter, Cloud Function va venir calculer le nombre de documents dans la collection que je lui ai indiquée.
Je n’ai plus qu’à l’utiliser dans mon code en front, de la manière qui suit :
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<int> fetchDocumentCount(String collectionName) async {
try {
final url = Uri.parse(
"https://url_de_votre_fonction"); //Remplacer par l'URL de votre fonction, trouvable dans Cloud Function
final response = await http.get(url);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data['count'] ?? 0;
} else {
throw Exception("Erreur : ${response.statusCode}");
}
} catch (e) {
print("Erreur lors de l'appel de la fonction Cloud : $e");
return 0;
}
}
Compter le nombre de documents dans Firebase, suite à un évènement
Enfin, la dernière manière de déclencher votre fonction est de le faire lors d’un évènement, comme lorsque l’utilisateur s’enregistre, quand un nouveau document est ajouté, etc.
Voici comment procéder :
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
exports.updateDocumentCountOnWrite = functions.firestore
.document("your_collection_name/{docId}")
.onWrite(async (change, context) => {
try {
const collectionName = "your_collection_name";
// Récupérez tous les documents de la collection
const docsSnapshot = await db.collection(collectionName).get();
// Comptez les documents
const count = docsSnapshot.size;
// Enregistrez le résultat dans un document spécifique
await db.collection("metadata").doc("documentCount").set({
count: count,
lastUpdated: admin.firestore.FieldValue.serverTimestamp()
});
console.log(`Nombre de documents dans ${collectionName} : ${count}`);
} catch (error) {
console.error("Erreur lors de la mise à jour du comptage des documents :", error);
}
});
Cette fonction se déclenche à chaque fois qu’un document est ajouté, modifié ou supprimé dans la fonction que vous aurez renseigné (functions.firestore.document("your_collection_name/{docId}").onWrite)
. Vous n’avez plus qu’à modifier cette partie selon vos besoins.