Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firestore collection query as stream in flutter

I'm trying to query a few documents from a collection, this query should listen to changes made in the queried documents, so I'd need a stream. I'm doing following (in Dart/Flutter)

  Stream<List<MatchRequest>> _getNewMatches() {
    return Collection<MatchRequest>(path: 'requests')
        .ref
        .where('status', isNull: true)
        .where('users', arrayContains: ['$currentUid'])
        .orderBy('last_activity')
        .snapshots()
        .map((list) => list.documents.map(
            (doc) => Global.models[MatchRequest](doc.data) as MatchRequest));
  }

(The object Collection sets the path to the ref in it's constructor, eg: ref = db.collection($path) and the map makes a model of the results)

Then I'm using a StreamBuilder with stream invoking the method above and builder checking if snapshot.hasData. But it keeps loading, snapshot.hasData keeps being false. What am I doing wrong here?

EDIT:

  1. My firestore security rules contain:

    match /requests/{requestId} {
        allow read: if isLoggedIn();
        allow write: if isLoggedIn();
    }
    
  2. When removing every where and orderBy, it doesn't find anything as well. And there are documents present in the requests-collection

  3. When trying to query only 1 document as a stream from the requests-collection, he does find the result

  4. Is it because I should add indexes to my firestore indexes? But this won't solve my first problem which is that even without where and orderBy, it doesn't get any data

like image 910
SimonartM Avatar asked Dec 18 '19 13:12

SimonartM


1 Answers

I've written a simple example of it seems to be like what you are trying to do but are missing the listen() method:

Firestore.instance.collection('collection')
  .where('field', isEqualTo: 'value')
  .orderBy('field')
  .snapshots()
  .listen((QuerySnapshot querySnapshot){
    querySnapshot.documents.forEach((document) => print(document));
  }
);

This is just an example of how you can take the data from a Firestore Stream and use it on a StreamBuilder:

class _MyHomePageState extends State<MyHomePage> {
  Stream dataList;

  @override
  void initState() {
    dataList = Firestore.instance.collection('collection')
      .where('field', isEqualTo: 'value')
      .orderBy('field')
      .snapshots();

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: StreamBuilder(
          stream: dataList,
          builder: (context, asyncSnapshot) {
            if(asyncSnapshot.hasError)
              return Text('Error: ${asyncSnapshot.error}');

            switch (asyncSnapshot.connectionState) {
              case ConnectionState.none: return Text('No data');
              case ConnectionState.waiting: return Text('Awaiting...');
              case ConnectionState.active:
                return ListView(
                  children: asyncSnapshot.data.map((document) => Text(document['value'])),
                );
              break;
              case ConnectionState.done: return ListView(
                children: asyncSnapshot.data.map((document) => Text(document['value'])),
              );
              break;
            }
            return null;
        }),
      ),
    );
  }

} 
like image 173
João Soares Avatar answered Oct 18 '22 23:10

João Soares