Search code examples
fluttergoogle-cloud-firestoreflutter-futurebuilder

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


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'));
                            });
                      }
                    },
                  )