I am using Firebase 8.10.0 with Vue js 2.6.14
I am trying to query in Firestore about the documents that are less than 3 km away from my location
And discovered that I could not do this query in firestore, I was frankly disappointed
Then after watching a video by Frank van Puffelen on YouTube “Querying Firebase and Firestore”1
I understood that the best way to do this query is through Geohash
So now I’m using ngeohash
to convert lat long to geohash code then geofirestore
to query ( i am not using geofirestore to add the data to firestore because i don’t find a way to add doc with specific id or update an existing doc with geofirestore )
convert lat long to geohash code
import geohash from "ngeohash"; const ask = async () => { try { const loc = await new Promise((resolve, reject) => { navigator.geolocation.getCurrentPosition(resolve, reject, { enableHighAccuracy: true, }); }); const { latitude, longitude, accuracy } = loc.coords; return { lat: latitude, lng: longitude, accuracy: accuracy, geohash: geohash.encode(latitude, longitude) }; } catch (err) { console.log(err); } };
add data to firestore
ref.set({ g: { geopoint: new db.GeoPoint(lat, lng), geohash: geohash }, ...data }, { merge: true }).then(() => { console.log("Done"); });
query from firestore
let query = geocollection.near({ center: new db.GeoPoint(lat, lng), radius: 3 }); query.get().then((data) => { console.log(data.size); });
Is what I’m doing right is this the best way to query by location in firestore? and does geofirestore increase the number of readings because I made a query a while ago and the result was only 5 from 1000 documents, but I found that more than 60 readings were recorded in the Firebase console. Is this normal or was it only supposed to be 5 readings?
Advertisement
Answer
Geohashes allow you to query documents within a certain geographic areas. These areas may overlap with the distance from a specific point that you specify, but you will usually need to query multiple ranges of geohashes to get all documents around a certain point.
A simple visualization of this based on what I showed in the video you linked:
So the query here is to return all documents within the gray circle. But in order to get those documents, we need to query all four colored ranges of geohashes.
If you have a relatively uniform distribution of the documents, you might end up with this:
Each pin in this image is a document that is read by Firestore, but only the green pins are documents that fall within the range you actually wanted.
In my experiments, for a uniform distribution of documents, you end up reading between 2x and 10x more documents than needed with this approach. If this overreading is a cost concern for you, consider using the Realtime Database and its geofire library for your geoqueries. While the overreading will be the same, the billing structure is based on bandwidth and the amount of bandwidth consumed by the geoindex is pretty minimal there.