flutterfirebasedartgoogle-cloud-firestore

How to output number of documents which match a query?


I would like to output the number of documents that match a particular query, the query is a boolean value, so display the number of documents that have "true" value. I found several questions related to this in Stack Overflow but only the following code comes close to my needs.

The following code prints out the correct number in console but I need help outputting it on screen.

final Future<void> activityDone = FirebaseFirestore
      .instance
      .collection('user')
      .doc(FirebaseAuth.instance.currentUser!.uid)
      .collection('list')
      .doc(widget.docId).collection('activity').where("status", isEqualTo: true)
      .count().get().then(
        (res) => print(res.count),
    onError: (e) => print("Error completing: $e"),
  );

I can't get this count code to work.

String count = activityDone.toString();

I would like to use the count code in a text like this

Text("Activities done = $count"),

Full Code

child: StreamBuilder(
  stream: FirebaseFirestore.instance
          .collection('user')
        .doc(FirebaseAuth.instance.currentUser!.uid)
          .collection('list')
          .doc(widget.docId).collection('activity').orderBy('xTimeStamp', descending: false)
        .snapshots(),
  ),
  builder: (context, snapshot) {

    final xSnapshot = snapshot.data?.docs;

    final Future<void> activityDone = FirebaseFirestore
      .instance
      .collection('user')
      .doc(FirebaseAuth.instance.currentUser!.uid)
      .collection('list')
      .doc(widget.docId).collection('activity')
      .where("status", isEqualTo: true)
      .count()
      .get().then(
        (res) => print(res.count),
        onError: (e) => print("Error completing: $e"),
    );

    String count = activityDone.toString();

    if (xSnapshot == null) {
      // Error
    }, else {
      Text("Activities done = $count"),
    }    
}

Errors enter image description here enter image description here


Solution

  • In your builder you're trying to make asynchronous code behave synchronously, which doesn't work.

    Since your code in builder uses get(), which returns a Future, you'll need to return a FutureBuilder from there to handle the async Future.

    builder: (context, snapshot) {
      // final xSnapshot = snapshot.data?.docs;
    
       final Future<int?> activityDone = FirebaseFirestore.instance
          .collection('user')
          .doc(FirebaseAuth.instance.currentUser!.uid)
          .collection('list')
          .doc(widget.docId)
          .collection('activity')
          .where("status", isEqualTo: true)
          .count()
          .get()
          .then((res) => res.count);
    
      return FutureBuilder(
        future: activityDone,
        builder: (context, snapshot) {
          if (snapshot.hasError) return Text('ERROR: ${snapshot.error}');
          if (!snapshot.hasData) return CircularProgressIndicator();
          final count = snapshot.data!;
          return Text('Activities done = $count');
        }
      );
    }
    

    Note: I didn't run this code right now, so syntax errors are possible. When such an error occurs, try to solve then on your own before posting back here please. LLMs (such as ChatGPT and Gemini) as quite good at explaining syntax errors in code blocks.

    It's weird that you're not using xSnapshot in the builder though.