How can I implement Stream to get list of sub collection for each docs ? -flutter

Issue

I’m try to get sub collection from each doc ex.clothes,notifer witch I have more docs , that means I don’t know its id ,My bossiness Logic was to fetch the main collection for getting all the documents and then for each doc get its sub collection and I did that with Future implementation ,but I can’t do it using Stream to return the final Sub Collection SnapShots ex.properitres for listing to changes . by Future it rebuild every time and if I stop widget rebuilding by AutomaticKeepAliveClientMixin I could not get any Firesotre changes . Thanks in advance .enter image description here

enter image description here

here is my Future implementation but again I need this implementation by Stream ^_^:

Future<List<Category>> getPropertiesDocs() async {
    List<QueryDocumentSnapshot> _firstListOfDocs = [];
    List<Category> _categorListOfDocs = [];
    List<QueryDocumentSnapshot> _secoudListOfDocs = [];

    final QuerySnapshot result = await _firebaseFirestore.collection('categories').get();
    result.docs.forEach((element) {
      // print(element.id);
      _firstListOfDocs.add(element);
    });
    for (var i in _firstListOfDocs) {
      final QuerySnapshot snapshot2 = await i.reference.collection("properties").get();
      snapshot2.docs.forEach((element) {
        _secoudListOfDocs.add(element);
        _categorListOfDocs.add(Category.fromSnapShpt(element));
      });
    }
    _firstListOfDocs.clear();
    _secoudListOfDocs.clear();
    return _categorListOfDocs;
  }

Solution

From your future implementation,

  1. You want to get all documents in categories collection.
  2. For each document in categories collection, you want to get the properties subcollection.

For the first requirement, we can simply stream the categories collection.
For the second requirement, it is not advisable to stream properties collection from each categories subcollection. This won’t scale well with large datasets.

Instead we will stream the collectionGroup properties. Streaming the collection group properties will fetch all collections with the name properties (no matter the location). To effectively use this, no other collection should be named properties (except the ones you want to fetch), or you rename your collection to something distinct like properties_categories.

// this streamBuilder will fetch stream for categories collection.
StreamBuilder<QuerySnapshot>(
  stream: _firebaseFirestore.collection('categories').snapshots(),
  builder: (BuildContext context,
      AsyncSnapshot<QuerySnapshot<Delivery>> snapshot) {
    if (snapshot.hasError) return Message();
    if (snapshot.connectionState == ConnectionState.waiting)
      return Loading();
      print('categories snapshot result');
      print(snapshot.data.docs.map((e) => e.data()).toList());
      // _firstListOfDocs is given below (renamed to _categoryDocs)
      List<QueryDocumentSnapshot> _categoryDocs = snapshot.data.docs;

    // this streamBuilder will fetch all documents in all collections called properties.
    return StreamBuilder<QuerySnapshot>(
      stream: _firebaseFirestore.collectionGroup('properties').snapshots(),
      builder: (BuildContext context,
          AsyncSnapshot<QuerySnapshot> propertiesSnapshot) {
        if (propertiesSnapshot.hasError) return Message();
        if (propertiesSnapshot.connectionState == ConnectionState.waiting)
          return Loading();

        print('properties snapshot result');
        print(propertiesSnapshot.data.docs.map((e) => e.data()).toList());
        // _secoudListOfDocs is given below (and renamed to _propertiesDocs)
        List<QueryDocumentSnapshot> _propertiesDocs = propertiesSnapshot.data.docs;
        // _categorListOfDocs is given below (and renamed to _categories)
        List<Category> _categories = propertiesSnapshot.data.docs
          .map((e) => Category.fromSnapShpt(e)).toList();
        // return your widgets here.
        return Text('Done');
      },
    );
  },
)

If your reason for fetching categories collection data is simply to loop over it and fetch properties collection, then you can delete the first streamBuilder above since we do not need to use it to fetch properties collection.

Answered By – Peter O.

Answer Checked By – Cary Denson (FlutterFixes Admin)

Leave a Reply

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