Compter les documents dans une collection Firebase


Avatar de Pierre Courtois

Compter les documents d’une collection Firebase peut s’avérer utile pour construire certains de vos widgets ou mettre en place des fonctions. Dans ce guide, je vous explique comment mettre cela en place de manière automatisée, avec Cloud Functions.


fonction de comptage de documents

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.

Si vous ne l’avez pas encore fait, vous devrez d’abord mettre en place les fonctions clouds pour votre projet Flutter.

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.

Avatar de Pierre Courtois