R7.06.1 · Geospatial — dive
GEOADD and GEOSEARCH.
Store locations and query by radius using Valkey’s core GEO commands — longitude first, then latitude. The lon-before-lat order is the single most common source of a GEO bug.
Select a command below to see what it does. Then the radius-search visual shows which cities fall inside a 600 km ring around San Francisco.
Longitude first — the classic gotcha
geospatial.md.txt · Adding LocationsGEOADD locations -122.4194 37.7749 "san_francisco" # lon FIRST, then lat GEOADD locations -73.9857 40.7484 "new_york" GEOADD locations -0.1276 51.5074 "london" # multiple in one call GEOADD locations -122.4194 37.7749 "san_francisco" -73.9857 40.7484 "new_york"
GEOADD takes longitude before latitude. This follows the GeoJSON
specification ([lon, lat]), but reverses the everyday geographic convention
(“37.7749°N, 122.4194°W”). Passing arguments in the wrong order silently stores every
point in the wrong location — Valkey accepts the call without error.
The same order applies to FROMLONLAT in GEOSEARCH and to the coordinates
returned by GEOPOS. State the convention once at the boundary and enforce it everywhere.
Calling GEOADD on an existing member name replaces its coordinates. The return value is
the count of newly added members; an update returns 0.
GEOADD is a core Valkey
command — no module required. It stores coordinates as a 52-bit interleaved geohash integer used as the
ZSET score; the maximum precision is approximately ±0.6 m. Cite:
valkey.io/commands/geoadd.The lon-before-lat argument order is consistent with GeoJSON but counterintuitive for anyone
who writes latitudes first. One wrong argument silently maps a city to the wrong hemisphere. Name the order
explicitly in every GEOADD call comment.
GEOPOS, GEODIST, and GEOHASH
geospatial.md.txt · Retrieving Coordinates / Calculating Distance / GeohashGEOPOS retrieves stored coordinates as [longitude, latitude]. The returned
values may differ by a few microdegrees from the input because coordinates are stored as 52-bit geohash
integers (precision ±0.6 m). Unknown members return nil.
GEODIST measures the great-circle distance between two stored members. Four unit options
cover all common applications:
| Unit | Code | Use-case |
|---|---|---|
| metres | m | Precision within a city block |
| kilometres | km | Standard for most apps |
| miles | mi | US-centric distance display |
| feet | ft | Indoor / floor-level precision |
GEOPOS locations "san_francisco" # → [[-122.41940..., 37.77490...]] (lon-first, ±0.6 m from stored geohash) GEODIST locations "san_francisco" "new_york" km # → 4129.09 GEODIST locations "san_francisco" "london" mi # → 5367.21 GEOHASH locations "san_francisco" # → ["9q8yy9mfry0"] (the geohash string — 11 chars ≈ ±2.4 m)
GEOHASH returns the human-readable geohash string. Longer strings encode finer precision;
the stored ZSET score is the same value decoded to a 52-bit integer. The string form is useful for
debugging and for exporting coordinates to other geospatial systems.
GEOPOS is the inverse of GEOADD; GEODIST is the
great-circle distance calculator; GEOHASH exposes the internal encoding as a human-readable
string. All three are introspection over the ZSET that GEOADD builds.
GEOSEARCH — origins, shapes, and output options
geospatial.md.txt · Searching by Radius / Search OptionsGEOSEARCH supersedes the deprecated GEORADIUS and
GEORADIUSBYMEMBER (removed from the recommended API since 6.2). Two origin forms:
FROMMEMBER name— centre the search on a stored memberFROMLONLAT lon lat— centre on arbitrary coordinates (lon first)
Two shape forms: BYRADIUS r unit (circle) and BYBOX w h unit (rectangle
centred on the origin, width × height). The radius-and-box queries dive covers both shapes in depth.
# from a stored member, circle, results closest-first GEOSEARCH locations FROMMEMBER "san_francisco" BYRADIUS 500 km ASC # from arbitrary coords, with all output options GEOSEARCH locations FROMLONLAT -122.4 37.8 BYRADIUS 50 km WITHCOORD WITHDIST COUNT 10 ASC
Output options shape the result. Any combination is valid:
| Option | Adds to each result |
|---|---|
WITHCOORD | The stored [lon, lat] |
WITHDIST | Distance from the origin in the search unit |
WITHHASH | The raw 52-bit geohash integer |
COUNT N | Stop after N results — combine with ASC for “nearest N” |
ASC / DESC | Sort by distance ascending or descending |
FROMLONLAT + BYRADIUS + COUNT N + ASC is the “find the N nearest”
pattern. Add WITHDIST when the client needs to display the distance; omit it to keep the
result set leaner when order is all that matters.
Radius-search visual — which cities fall inside?
interactive · GEOSEARCH FROMLONLAT BYRADIUSThe diagram below shows San Francisco (the search origin, in red) and five cities. Adjust the radius
slider; the ring grows or shrinks and cities inside the radius turn green — exactly what
GEOSEARCH … FROMLONLAT -122.4 37.8 BYRADIUS <r> km ASC returns. Distances are
great-circle values, computed from the stored coordinates above.
GEOSEARCH locations FROMLONLAT -122.4 37.8 BYRADIUS <radius> km ASC.
Cities inside the radius are the result set.The visual uses the same coordinate set as figure 17. The ring radius scales with the SVG
viewBox — one pixel here represents roughly 12 km at this zoom. The actual
GEOSEARCH command uses great-circle distance, which is what the distance values in the
readout reflect.
A radius search returns every member within the circular region centred on the origin,
sorted by distance. The COUNT option stops the scan early — useful when only the
nearest N results matter and scanning the full set is unnecessary.
Grounding — core Valkey, no consumer surface
geospatial.md.txt · figure 17 · figure 19GEOADD encodes (lon, lat) into a 52-bit interleaved geohash integer stored
as a ZSET score; GEOSEARCH is a bounded range-scan over that score space. The lon-before-lat
order is the external interface; the internal representation is a sorted integer.
The natural homes are a store locator (GEOADD restaurants … + GEOSEARCH …
BYRADIUS 5 km) and a ride-share driver index (GEOADD drivers … updated on each
GPS ping). codemojex has no location dimension — it is a location-agnostic Telegram emoji game.
GEO commands are core Valkey; the store-locator and ride-share patterns are the standard worked examples. codemojex ships no geo surface — players guess emoji, and nothing in the game is placed in space.
References
sources · relatedSources
- Valkey — GEOADD — add members with lon/lat; the lon-before-lat convention.
- Valkey — GEOSEARCH — FROMMEMBER/FROMLONLAT, BYRADIUS/BYBOX, output options; supersedes GEORADIUS.
- Valkey — GEODIST — great-circle distance between two members in m/km/mi/ft.
- Valkey — GEOPOS — retrieve stored coordinates; geohash precision note.
Related in this course
- R7.06 · Geospatial — module hubfull command surface, metadata pattern, geofencing
- R7.05 · Vectors & similarity searchthe preceding modeling-family module
- R7.04 · Bitmapsboolean flags at 1 bit per entity
- R4 · Time, delay & prioritythe sorted-set-as-a-clock family — same encode-into-score move