viic
viic

Reputation: 41

Flutter Firebase Cloud Firestore get stream of list of documents by their ids

Hey guys I have two top level collections, a user and a tabs collection. Within each user document I have an array field of document ids with each element in the array representing a document in the tabs collection (sort of like a reference or a pointer to that document) and I would like to listen to real time changes in the users/document with the list of ID's and to listen for changes to the corresponding documents in the tabs collection.

Below is my code so far and there are two issues with it. The stream isn’t working client side - I’m not receiving an updated snapshot when I update the document in cloud firestore. Also in order for me to get a list of tabIds I am currently making a query to cloud firestore which returns a stream however, the whereIn operator only accepts a list of objects so I’m not to sure how to handle that.

data model screenshot

     Stream<List<Tab>> get tabs {
      var tabIds = _db.collection('users').doc(user.uid).snapshots().where((event) => event.get('tabs'));
      return _db
      .collection('tabs')
      .where(FieldPath.documentId, whereIn: tabIds)
      .snapshots()
      .map((list) =>
        list.docs.map((doc) => Tab.fromJson(doc.data())).toList());
     }

Upvotes: 4

Views: 3284

Answers (1)

Peter Obiechina
Peter Obiechina

Reputation: 2835

You can't directly listen to documents based on their ids, but you can add a field called docId (the value should be the id of the document) to each document then listen to collection with this where condition.

List listOfDocIds = []; // this is the list of your docIds
StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
  stream: FirebaseFirestore.instance
            .collection('users')
            .where('docId', whereIn: listOfDocIds),
  builder: (BuildContext context,
      AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
    if (snapshot.hasError) return Text('Something went wrong');
    if (snapshot.connectionState == ConnectionState.waiting)
      return CircularProgressIndicator();

    List<Map<String, dynamic>> data =
        snapshot.data.docs.map((e) => e.data()).toList();
    print(data);
    // you can build your widget here
    return ListView.builder(
      itemCount: data.length,
      itemBuilder: (context, i) {
        return ListTile(
          title: Text(data[i]['name']),
          // TODO: change 'name' to name of field in users document
        );
      },
    );
  },
),

Upvotes: 3

Related Questions