Flutter how to optimise Firestore store reads to prevent a lot of unnecessary reads

Viewed 447

I am building an where when the user logs in to the app, it shows all the user's information that are also registered on the app. With my init fetch method that fetches all the information it uses a large amount of read which came up to 1.3k reads from a few days of testing whilst there being only 4 users registered. which is unusually high.

My fetch method which fetches the users information from firestore

void loadUserProfiles() async {
    var firebaseUser = await FirebaseAuth.instance.currentUser();
    List<String> tempUsers = List<String>();
    List<String> tempNames = List<String>();
    List<String> tempImages = List<String>();

    imageUrl.clear();
    names.clear();
    userId.clear();

    tempUsers.clear();
    tempNames.clear();
    tempImages.clear();
    setState(() {
      isLoading = true; //Data is loading
    });

    // Adds all the values of each user from firestore to their list to compare
    await firestoreInstance
        .collection("users")
        .getDocuments()
        .then((QuerySnapshot snapshot) async {
      snapshot.documents.forEach((f) async {
        if (f.documentID != firebaseUser.uid) {
          tempUsers.add(f.data['userid']);
          tempNames.add(f.data['name']);
          tempImages.add(f.data['images'][0]);
        }
      });
    });

    // Adds user to list to load to user cards if doesnt exist in liked users firestore
    for (int i = 0; i < tempUsers.length; i++) {
      await firestoreInstance
          .collection("users")
          .document(firebaseUser.uid)
          .collection("liked_users")
          .document(tempUsers[i])
          .get()
          .then((value) async {
        if (!value.exists) {
          userId.add(tempUsers[i]);
          names.add(tempNames[i]);
          imageUrl.add(tempImages[i]);
        }
      });
    }

    setState(() {
      isLoading = false; //Data has loaded
    });
  }

The way i have done it is that it fetches all the data and stores them into three separate temporary lists. Then using those lists i would read through the firestore again to compare if the user's id that the current user has liked exists or not in a collection.

It also gets worse since im using a bottom nav bar and whenever that page is clicked it starts my load method again which uses more reads.

1 Answers

There are several things you can do:

  1. Pagination In your code getDocuments you seem to be retrieving EVERY SINGLE user. Generally, with huge collections (usually to feed a list), we try to fetch only those that are going to be in view so say first 20 documents. Once we reach max scroll extent we fetch the next 20.

  2. For your reload problem, try to do your fetch in say an initState function. Place it somewhere so that it will only run when it needs to. I don’t know your app structure but let’s say in my app. I had placed all initial retrieval of essential data that generally doesn’t change in my initial login logic instead of doing so every time we route to a page that needs the data

  3. Additionally, Google also has an official guide to things like Cursors. Check it out and see if other solutions can be more appropriate.

Related