DarshanGowda0 / GeoFlutterFire

:fire:GeoFlutterFire:fire: is an open-source library that allows you to store and query firestore documents based on their geographic location.
https://youtu.be/MYHVyl-juUk
MIT License
305 stars 261 forks source link

How to use GeoFlutterFire like a firestore stream? #16

Closed momsenmeister closed 5 years ago

momsenmeister commented 5 years ago

Hi @DarshanGowda0, first of all, thanks a lot for creating this awesome library!

Unfortunately I have some trouble getting it working the same way like my basic firestore streams. So far I include my firestore queries directly as a stream in the StreamBuilder widget like this: StreamBuilder( stream: Firestore.instance.collection('events') .where("eventTime", isGreaterThanOrEqualTo: DateTime.now().millisecondsSinceEpoch) .where("eventStatus", isEqualTo: "created") .orderBy('eventTime').snapshots(), Here, .snapshots() returns a Stream<QuerySnapshot>, whereas your example returns a Stream<List<DocumentSnapshot>>.

Maybe you could provide an example how to use GeoFlutterFire the same way like the firestore query? I don't really get the concept of the listener, and your readme says that I should be able to use geoRef.data() or geoRef.snapshot() to use it the same way like my other streams. I just can't figure out how :-)

Also, if I follow your readme exactly and use the listener, I receive this error: com.google.firebase.firestore.FirebaseFirestoreException: INVALID_ARGUMENT: cursor position is outside the range of the original query

Thanks a lot, Michael

DarshanGowda0 commented 5 years ago

Hi @momsenmeister, this should help you :smile:

initialize the stream

@override
  void initState() {
    super.initState();
    geo = Geoflutterfire();
    var radius = BehaviorSubject(seedValue: 1.0);
    GeoFirePoint center = geo.point(latitude: 12.96, longitude: 77.64);
    stream = radius.switchMap((rad) {
      var collectionReference = _firestore.collection('locations');
      return geo.collection(collectionRef: collectionReference).within(
          center: center, radius: rad, field: 'position', strictMode: true);
    });
  }

and you streamBuilder would look like this,

StreamBuilder(
            stream: stream,
            builder: (BuildContext context,
                AsyncSnapshot<List<DocumentSnapshot>> snapshots) {
              if (snapshots.connectionState == ConnectionState.active &&
                  snapshots.hasData) {
                print('data ${snapshots.data}');
                return Container();
              } else {
                return Center(child: CircularProgressIndicator());
              }
            },
          ),
momsenmeister commented 5 years ago

Hi @DarshanGowda0,

thanks a lot! I got it sort of working now if I use a simple query like the one you stated: _firestore.collection('locations')

But I still have two problems left:

  1. It doesn't work when I use a more complex firestore query like this one:
    Firestore.instance.collection('events')
    .where("eventTime", isGreaterThanOrEqualTo: DateTime.now().millisecondsSinceEpoch)
    .where("eventStatus", isEqualTo: "created").orderBy("eventTime");

I receive the following error and don't get any results from the query: com.google.firebase.firestore.FirebaseFirestoreException: INVALID_ARGUMENT: cursor position is outside the range of the original query.

Maybe that could be due to the restriction of firestore that doesn't allow queries with range filters on different fields?

My goal with geoflutterfire was to filter by time (>= now && <= tomorrow) and position (radius < 50) at the same time.

  1. Whenever I add an item to firestore, the stream doesn't properly update. Instead, the results are just appended to the list, resulting in every item being twice in the list. Maybe solved with #13
DarshanGowda0 commented 5 years ago

Hey @momsenmeister, yes the problem with (1), as you guessed, is a drawback we have from the cloud_firestore side. As for (2), the issue is fixed in #19.

momsenmeister commented 5 years ago

@DarshanGowda0 Okay, but now I even don't get any results when using: Firestore.instance.collection('events').orderBy("eventTime") whereas Firestore.instance.collection('events') works fine.

So, even the orderBy does not work?

DarshanGowda0 commented 5 years ago

@momsenmeister orderBy is used internally in the within function, so using another orderBy will mess with the order. We could add the orderBy after the orderBy of geohash, but that defeats the purpose. You could instead sort it on the client side?

momsenmeister commented 5 years ago

@DarshanGowda0 I see :-) My use case is to show a list of social events that are filtered by radius but sorted by time. Initially I tried to filter both on radius and time span, but so far I couldn't find any solution apart from having one filter on the client. But i'll keep trying... I think this issue can be closed than.

Maybe you want to include these two aspects of this issue to your readme?

Thanks a lot, Michael

DarshanGowda0 commented 5 years ago

Yes @momsenmeister, I will include those in the readme. Thanks 😄

saipavankumar-muppalaneni commented 4 years ago

CircularProgressiveIndicator is on forever, and when I used // stream.listen((List documentList) { //Here it throws error documentList.forEach( (e) {something}
}) // Please brother leave a solution for this, I have been stuck on this for days.