In a future builder, I use the following future that should return the number of documents (The collection stores "seen" event of an ad detailed view):
/// Stores and returns the document [id].
static Future<int> getCount({required String? adId}) {
if (adId == null) return Future<int>.value(0);
// = Actually store the document
final c = FirebaseFirestore.instance
.collection(collectionName)
.where("adId", isEqualTo: adId)
.snapshots()
.length;
return c;
}
The FutureBuilder
:
FutureBuilder(
future: ClassifiedAdSeen.getCount(adId: ad.id),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Icon(Icons.error);
} else if (!snapshot.hasData) {
return const CircularProgressIndicator();
}
final count = snapshot.data ?? "—";
return Text("$count");
}),
But it never hasData
nor hasError
, the spinner keeps on progressing.
Any idea Where the issue is, please?
[UPDATE]
By fetching the documents, I get the completion and the count with no problem. But fetching the documents is a waste of memory and bandwidth, isn't it?
So what would be the best way of fetching only the document count?
/// Stores and returns the document [id].
static Future<int> getCount({required String? adId}) async {
if (adId == null) return 0;
// = Actually store the document
final c = await FirebaseFirestore.instance
.collection(collectionName)
.where("adId", isEqualTo: adId)
.get();
return c.size;
}
CodePudding user response:
In your case, which is getting only the length of documents from your query, there is also a count()
method that returns an AggregateQuery
, which you don't get billed for, it returns only the length of the documents, nothing else.
Give it a try:
/// Stores and returns the document [id].
static Future<int> getCount({required String? adId}) async {
if (adId == null) return 0;
// = Actually store the document
final c = await FirebaseFirestore.instance
.collection(collectionName)
.where("adId", isEqualTo: adId)
.count()
.get();
return c.count;
}
CodePudding user response:
The snapshots()
returns a Stream
, since you said that you want just to get the number of the documents on your query, consider using get()
, in addition that you need an async/await
in your method, then return the QuerySnapshot
in your Future
method, then call the length on it's docs
property :
static Future<QuerySnapshot> getQuerySnapshot({required String? adId}) async {
final c = await FirebaseFirestore.instance
.collection(collectionName)
.where("adId", isEqualTo: adId)
.get();
return c;
}
FutureBuilder
:
FutureBuilder<QuerySnapshot>(
future: ClassifiedAdSeen.getQuerySnapshot(adId: ad.id),
builder: (_, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Icon(Icons.error);
} else if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
final count = snapshot.data.docs.length ?? "—"; // like this
return Text("$count");
}),