The core query in ChargeDisha is boring to describe and annoying to implement: “show me charging stations within 10km of where I am.” If I were on Postgres I’d install PostGIS, add a GiST index, and be done. But ChargeDisha runs on Firestore, because the rest of the app (check-ins, gamification, cloud functions) fits Firestore well and I didn’t want to run a second database for one query.
Firestore has no spatial types. What it does have is fast range queries on string fields. That’s enough, if you encode location as a string that preserves proximity. That’s exactly what a geohash is.
How the encoding works
A geohash interleaves the bits of latitude and longitude and encodes the result in base32. The property that matters: strings that share a prefix are geographically close. tekze and tekzf are neighboring cells; tekze and w21zd are different cities.
Each extra character divides the cell roughly 32 ways, so precision is a knob:
5 chars ≈ 4.9 km × 4.9 km
6 chars ≈ 1.2 km × 0.6 km
7 chars ≈ 153 m × 153 m
I store a 7-character geohash on every station document. Seven characters is precise enough that a cell never contains more than a handful of stations, and coarse enough that the index stays cheap.
The query
To find stations within 10km, I don’t query at 7 characters. I truncate to the precision whose cell size covers the radius, then query that cell and its eight neighbors. The neighbors matter: your position can sit right on a cell boundary, and a station 200m away can live in the adjacent cell with a completely different hash prefix.
Each cell lookup is a prefix range query, which Firestore serves straight off the index:
start = cell # e.g. "tekz"
end = cell + "~" # ~ sorts after every base32 char
docs = stations.order_by("geohash").start_at(start).end_at(end)
Nine index-backed range reads, then one pass in the Flask service to compute exact haversine distances and drop anything outside the true radius (the cells cover a square, the user asked for a circle). The whole thing comes back in well under 100ms, which on a mobile connection is indistinguishable from instant.
What I’d tell someone considering this
Use the boring spatial database if you have one. But if your data already lives in a key-value or document store, a geohash column plus the neighbor-cell trick gets you real proximity search with nothing but a sorted index — no new infrastructure, no extension, nothing to operate. For a nights-and-weekends project where I’m the whole ops team, that last part is the feature.