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

Is it possible to use as one query instead of stream? #27

Open felpsio opened 5 years ago

felpsio commented 5 years ago

I need to use the geolocation query just once in a while instead of keeping a stream open. Is there a way to do it in the current implementation?

If anyone had an idea how to implement this in the plugin I can help with the implementation/PR

DarshanGowda0 commented 5 years ago

This is the actual query, and its a run on 9 geo-hashes - 1 center, and 8 surroundings which is then used to create streams as shown here. So, there's no single query that can be exposed! The streams from all 9 queries are merged and a further filtered on distance. Hope this helps

felpsio commented 5 years ago

Thank you @DarshanGowda0. I need to query just once in a while for a limited number of results. I'm developing a newsfeed of posts that has a distance filter. So soon I gonna try to get the results just once instead of keep listening all the time for the answers.

Your reply gave me some ideas on how to do it :).

DarshanGowda0 commented 5 years ago

Happy to help 😄 I guess we'll need a getDocuments() with Futures implementation as well, along with streams? replacing ref.snapShots() with ref.getDocuments() here should help you get futures instead of streams. I'll try to write another within function for just this.

felpsio commented 5 years ago

Yes. Have something like getDocuments() would be very helpful. I'm finishing other features, and then I'll come back to this need :)

mike-gallego commented 5 years ago

@felipecesar42 Did you manage to get only 1 result to pop up? I also don't want it to listen all the time.

felpsio commented 5 years ago

Not yet. I'm finishing other things before being able to focus on this feature. But if you decide to start I can try to help :)

Haves1001 commented 5 years ago

This is the actual query, and its a run on 9 geo-hashes - 1 center, and 8 surroundings which is then used to create streams as shown here. So, there's no single query that can be exposed! The streams from all 9 queries are merged and a further filtered on distance. Hope this helps

I was wondering when looking at the method if that actually still works if you get near the poles of the earth - a location where the tiles tend to get very small? I would think that int precision = Util.setPrecision(radius); in collection.dart should not only take the radius into account but also the location of the query.

awhitford commented 5 years ago

I had a query like this:

    return Firestore.instance
        .collection('places')
        .getDocuments()
        .then((data) => data.documents
            .map((doc) => Place(
                  id: doc["id"],
                  title: doc["title"],
                ))
            .toList());

I changed it to use within like:

    return _geo
        .collection(collectionRef: Firestore.instance.collection('places'))
        .within(
            center: center,
            radius: 100,
            field: 'geoLocation',
            strictMode: true)
        .first
        .then((documents) => documents
            .map((doc) => Place(
                id: doc["id"],
                title: doc["title"],
                ))
            .toList());

Note that I used first to transform the Stream into a Future.

gnalFF commented 5 years ago

I am having a similar issue, however the reasoning to have a one time shot query is that the underlying stream is not canceled, when using @awhitford way of converting it into a future The collection I query is protected by security rules, which leads then to exceptions on the stream, when signing out:

W/Firestore(15056): (19.0.0) [Firestore]: Listen for Query(rides order by start_location.location.geohash, name) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null} I/System.out(15056): com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions.

I suspect the issue is the returned broadcaststream.

Maybe I oversee something, looking forward for feedback

felpsio commented 5 years ago

Hi,

I just came back to this feature. Looks like it's impossible to convert to a Query. The best thing we can do is limit it artificially: create some kind of listener that keeps counting the number of documents retrieved and after reaching the threshold it cancels the subscription.

I searched for other implementations of this kind of query in other platforms. Looks like even in the web platforms (that have much more users than Flutter) they couldn't find a way to get this just a Query instead of Streams. Hopefully someday Firebase will improve their queries features, it's very limited so far and there's not a simple way to do complex queries even if the query isn't related to geolocation.

If someone finds another library in other platforms that solved this problem I would be happy to look their code and bring to this package.

@DarshanGowda0 do you know if I cancel the stream received from the within function if it will cancel all the substreams associated with it?

klaszlo8207 commented 5 years ago

Any news on this? This feature is missing!

tzvc commented 4 years ago

Agreed, this would be very useful

MartinJLee commented 4 years ago

This seems work.

    List<Place> ret = [];
    await geo
        .collection(collectionRef: queryRef)
        .within(center: center, radius: radius, field: 'location')
        .first
        .then((docs) {
      Future.forEach(docs, (DocumentSnapshot doc) {
        // parse place
       ret.add(place)
      }).whenComplete(() {
        return;
      });
    });
    return ret;

I'm not sure about the race condition this may cause. e.g. not all 9 queries available for the first steam. It would be nice if someone can confirm this.

lizbrownwood commented 4 years ago

@MartinJLee , how would you get distance like this?

MartinJLee commented 4 years ago

@MartinJLee , how would you get distance like this?

I'm not sure what distance you are after. Share your query code here so others can help you.

webertim commented 4 years ago

@lizbrownwood Do you mean something like this #87 ? There is a pull request to, which has to be accepted ( #88 ).

rinati commented 4 years ago

any update on that? I need a Future too. Listening all the time will lead to unnecessary bills from Firestore.

yulkin2002 commented 3 years ago

same here, would like to avoid unnecessary bills from Firestore for listening continuously

akcadev commented 3 years ago

The same problem continues..

Beautylivery commented 3 years ago

bump

awaik commented 3 years ago

Hey guys, sorry for such a delay. The author is very busy, from now on we help him to maintain the package.

@webertim I'll check your pull request. I think there will be some fixes because of such a delay with merging. Would you like to fix them or should we do it?

Just for your info - now we have two working branches - master and 3x_null_safety.

giorgio79 commented 1 year ago

How about using a StreamController like so https://stackoverflow.com/questions/60663818/flutter-how-to-refresh-streambuilder