I'm trying to get a documents based on a geohash upper and lower bounds. 'Location A' is the location of a user, and we're trying to find other locations that are within the bounds of 'Location A' in firebase. I was following this tutorial
https://levelup.gitconnected.com/nearby-location-queries-with-cloud-firestore-e7f4a2f18f9d
and checking with this website
https://www.movable-type.co.uk/scripts/geohash.html
The coordinates of 'location A' are 52.462570419161594, -2.0120335164758725
and the coordinates of 'Location B' are 52.46648448588268, -1.9841125656313279
. These are very close to eachother so, with the code below i'd assume that with the firebase query it'd return 'Location B' when querying from 'Location A's geohash but this isn't happening and it's because the getGeohashRange
function is returning the wrong value but i'm not sure what i'm doing wrong
Location A geohash = 'gcqd6' Location B geohash = 'gcqd6'
The upper & lower that the getGeohashRange
is returning =
lower: "mpt5mf52n18z"
upper: "mptmvc2wncyc"
This is the code & firebase query
// Get the geohash upper & lower bounds
GeoHashRange getGeohashRange({
required double latitude,
required double longitude,
double distance = 12, // miles
}) {
double lat = 0.0144927536231884; // degrees latitude per mile
double lon = 0.0181818181818182; // degrees longitude per mile
double lowerLat = latitude - lat * distance;
double lowerLon = longitude - lon * distance;
double upperLat = latitude + lat * distance;
double upperLon = longitude + lon * distance;
GeoHasher geo = GeoHasher();
var lower = geo.encode(lowerLat, lowerLon);
var upper = geo.encode(upperLat, upperLon);
return GeoHashRange(lower: lower, upper: upper);
}
class GeoHashRange {
late String upper;
late String lower;
GeoHashRange({
required this.upper,
required this.lower,
})
}
// Query firebase for locations
Stream<List<Garage>> getLocalGarages(Position position) {
GeoHashRange range = getGeohashRange(
latitude: position.latitude,
longitude: position.longitude,
);
var ref = _db
.collection('garages')
.where("geohash", isGreaterThan: range.upper)
.where("geohash", isLessThan: range.lower);
return ref.snapshots().map(
(list) =>
list.docs.map((doc) => Garage.fromJson(doc.data())).toList(),
);
}
Turns out theres a plugin that can actually help with this. This doc has some info https://firebase.google.com/docs/firestore/solutions/geoqueries#java and this is the plugin https://pub.dev/packages/geoflutterfire
This is my new code
Stream<List<Garage>> localGarages(Position position) {
var ref = _db.collection('garages');
GeoFirePoint center =
geo.point(latitude: position.latitude, longitude: position.longitude);
double radiusInKM = 20;
return geo
.collection(collectionRef: ref)
.within(center: center, radius: radiusInKM, field: 'position')
.map((x) => x.map((e) => Garage.fromJson(e.data()!)).toList());
}
There is an example of the 'position' field in the doc above