FlutterChicken
FlutterChicken

Reputation: 57

Fetching data from Firestore for a leaderboard screen not efficient

I want to show a list of top 25 players (fetched from Firestore) on a screen and currently this is how I implemented it:

late final Stream<QuerySnapshot> _mainScoreStream;



@override
  void initState() {
    futureAd = fetchAd();
    _mainScoreStream = FirebaseFirestore.instance
        .collection('users')
        .orderBy('current_score', descending: true)
        .where('current_score', isGreaterThan: 0)
        .limit(25)
        .snapshots();
    super.initState();
  }



@override
Widget build(BuildContext context) {
// Used to make text size automaticaly sizeable for all devices
final double unitHeightValue = MediaQuery.of(context).size.height * 0.01;

final user = Provider.of<UserModels?>(context);
return SafeArea(
  child: StreamBuilder<QuerySnapshot>(
    stream: _mainScoreStream,
    // ignore: missing_return
    builder: (context, snapshot) {
      if (snapshot.hasData) {
        return Expanded(
          child: ListView.builder(
            physics: BouncingScrollPhysics(),
            itemBuilder: (context, index) {
              DocumentSnapshot data = snapshot.data!.docs[index];
              return LeaderboardCard(
                currentScore: data['current_score'].toString(),
                name: data['name'],
                index: index,
                isCurrentUser: data.id == user!.uid,
              );
            },
            itemCount: snapshot.data!.docs.length,
          ),
        );
      } else if (!snapshot.hasData) {
        return Center(
          child: CircularProgressIndicator(
            strokeWidth: 2.0,
          ),
        );
      }
      return Container();
    },
  ),
);
 }
}

The leaderboard changes once a day, however with this implementation I get an extra 25 reads per user.

Is there a more efficient way to fetch this data or is this okay since my daily reads per one user are around 30 ?

EDIT: I am aware that over optimizing my reads/writes is not a good practice, but currently based on Firebase Pricing Calculator this could lead to a lot of daily reads, so not sure how to go about it, I could always decrease the limit or remove the Leaderboard completely

Upvotes: 0

Views: 110

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599946

If you change the leaderboard once per day, you could:

  • Calculate the leaderboard contents on a trusted system (your development machine, a server that you control, or Cloud Functions/Cloud Run), and store that in a separate document in Firestore. Then each client only has to read that document to get the entire leaderboard.

  • Create a data bundle with the query results each day on a trusted system, and distribute that to your users through a cheaper system (e.g. Cloud Storage or even as a document in Firestore again).

Upvotes: 1

Related Questions