Flutter Firestore – To retrieve document snapshots belonging to only a certain set of ids and show that data on screen

Issue

I am passing my constructor list of Firestore Document Ids and I want to retrieve and show data belonging to those ids only in my ‘LinksData’ collection.

So basically I want to retrieve the Document snapshot of all documents belonging to id’s that are in another list of mine (which I am passing in the constructor).

I could think of two methods :

  1. Using StreamBuilder, but according to what i know, with this i will either get all the documents snapshots in my collection or just one.
  2. Using Future Builder, i made this following function but when i use it , it shows the following error
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform

How can i do this? I don’t want to retrieve all the documents using stream builder, because that would affect my daily reads.

Here is the code of how i tried using FutureBuilder.

FutureBuilder<List<LinkCards>>(
                future: generateList(widget.linksDataIds),
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return Center(child: Text('Oops! Some Error Occurred!'));
                  } else {
                    if (!snapshot.hasData) {
                      return Center(child: CircularProgressIndicator());
                    }
                    return GridView.builder(
                        gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                          maxCrossAxisExtent: 220,
                          mainAxisSpacing: 12.0,
                        ),
                        itemCount: snapshot.data!.length,
                        itemBuilder: (context, index) {
                          return snapshot.data![index];
                        });
                  }
                },
              )

Here is my Future fucntion

  Future<List<LinkCards>> generateList(List<dynamic> listLinksDataId) async {
    FirebaseFirestore fireStore = FirebaseFirestore.instance;
    List<LinkCards> listCards = [];

    listLinksDataId.forEach((linkDataId) async {
      print(linkDataId);

      await fireStore
          .collection('LinksData')
          .doc(linkDataId)
          .get()
          .then((value) => {
                listCards.add(LinkCards(
                  link: value.get('link'),
                  linkTitle: value.get('title'),
                  linkImage: value.get('image'),
                  relatedCategories: value.get('categories'),
                  platform: value.get('platform'),
                ))
              });
    });
    return listCards;
  }

Here is an image of how my database is structured : enter image description here

Solution

Thanks for your replies, but i found a solution by modifying my database a little bit.
In ‘LinksData’ collection, I put a field (type array) which will contain all the categories. Then i used the StreamBuilder instead like this :

StreamBuilder<QuerySnapshot>(
                stream: FirebaseFirestore.instance
                    .collection('LinksData')
                    .where('categories', arrayContains: widget.categoryName)
                    .snapshots(),

                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return Center(child: Text('${snapshot.error}'));
                  } else {
                    if (!snapshot.hasData) {
                      return Center(child: CircularProgressIndicator());
                    }
                    return GridView.builder(
                        gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                          maxCrossAxisExtent: 220,
                          mainAxisSpacing: 12.0,
                        ),
                        itemCount: snapshot.data!.docs.length,
                        itemBuilder: (context, index) {
                          return LinkCards(
                              linkImage: snapshot.data!.docs[index].get('image'),
                              linkTitle: snapshot.data!.docs[index].get('name'),
                              link: snapshot.data!.docs[index].get('link'),
                              relatedCategories: snapshot.data!.docs[index].get('categories'),
                              platform: snapshot.data!.docs[index].get('platform'));
                        });
                  }
                },
              )

Answered By – Aamir Zaidi

Answer Checked By – Marie Seifert (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *