My problem
So, recently while working on a Flutter application, I struggled with a problem. Note, this is my first time using Firebase and essentially first time using Flutter as well.
Anyway, that problem was "How can I randomly select a 'tip' from my CloudFirestore and how can I count the number of tips in my database?"
First, I had to declare some data. The 'tips' Cloudstore collection reference, a Random, and a 'next' function that randomizes a number between a given min and max range.
class _TipsCardState extends State<TipsCard> {
CollectionReference tips = FirebaseFirestore.instance.collection('tips');
final _random = new Random();
String next(int min, int max) =>
(min + _random.nextInt(max - min)).toString();
String _randomTip;
int _tipsCount;
Future<int> countDocuments() async {
QuerySnapshot _myDoc = await tips.get();
List<DocumentSnapshot> _myDocCount = _myDoc.docs;
print(_myDocCount.length);
return _myDocCount.length;
}
Future<DocumentSnapshot> getTips() async {
_tipsCount = await countDocuments();
_randomTip = next(1, _tipsCount);
return await tips.doc(_randomTip).get();
}
The problem I ran in to was trying to accomplish this all in one single function. I'm pretty sure it can be done, but I struggled to get it working that way due to the multiple asynchronous actions used.
It was much easier to break it up into two separate functions. A function to count the documents and another to pull the tips from the database.
Future<int> countDocuments() async {
QuerySnapshot _myDoc = await tips.get();
List<DocumentSnapshot> _myDocCount = _myDoc.docs;
print(_myDocCount.length);
return _myDocCount.length;
}
First is the countDocuments function. This one is very simple. We're simply querying the Tips Collection, then grabbing the documents that belong to that collection and returning it's length. This gives us the amount of Documents in the Tips Collection.
Note: In Firestore, a Collection contains Documents.
Future<DocumentSnapshot> getTips() async {
_tipsCount = await countDocuments();
_randomTip = next(1, _tipsCount);
return await tips.doc(_randomTip).get();
}
When getTips
is called, you can see that it calls countDocuments
and sets it to a variable. This variable is then used to set the max value on the random number generator. This ensures that our max value is always dynamically set to equal the total tips in the database.
In the body of the app, the getTips
function is called within a FutureBuilder
widget. Since it returns the DocumentSnapshot
of the database.
The end result is displaying that tip within the app like so!
Note: You can also see some of the FutureBuilder
code in the screenshot, which I omitted from this post for brevity.
Hopefully this post made some sense! 😝 I'm trying to get better at explaining what I'm doing when it comes to coding. If there's anything I could explain better, let me know please!