Skip to content

Ask the HotKV docs

Answers come only from these docs and can be wrong; check the linked pages before you rely on them.

Geospatial

Last updated

Geospatial commands store a position (longitude and latitude) for each member of a key, and answer questions such as “how far apart are these two places?” and “which stores are within 10 km of this point, nearest first?”. They suit store locators, delivery and ride matching, and any “near me” feature.

A geospatial key is a sorted set whose scores encode positions, so TYPE reports zset and the sorted-set commands work on it too: ZREM removes a place, ZCARD counts them, and ZSCAN iterates them. The scores are the same ones Redis computes, so a geospatial key copied between Redis and HotKV keeps its positions.

GEOADD takes longitude first, then latitude, then the member name. Adding an existing member moves it.

127.0.0.1:6379> GEOADD cities 16.3738 48.2082 "vienna" 17.1077 48.1486 "bratislava" 19.0402 47.4979 "budapest"
(integer) 3
127.0.0.1:6379> GEODIST cities vienna bratislava km
"54.8333"
127.0.0.1:6379> GEODIST cities vienna budapest km
"214.1047"
127.0.0.1:6379> GEOSEARCH cities FROMLONLAT 16.5 48.2 BYRADIUS 100 km ASC WITHDIST
1) 1) "vienna"
2) "9.3996"
2) 1) "bratislava"
2) "45.4360"
127.0.0.1:6379> ZREM cities budapest
(integer) 1

Distances are returned with four decimals in the unit you ask for: m (the default), km, mi or ft. GEOPOS returns the stored coordinates of members, and GEOHASH returns them as standard 11-character geohash strings.

NX only adds new members, XX only moves existing ones, and CH makes the reply count moved members as well as added ones.

GEOSEARCH finds members inside a shape around a center:

  • Center: FROMLONLAT <lon> <lat>, or FROMMEMBER <member> to search around a stored place.
  • Shape: BYRADIUS <radius> <unit> for a circle, or BYBOX <width> <height> <unit> for a rectangle.
  • ASC or DESC sorts by distance; COUNT n limits the results (with ANY, HotKV returns as soon as it has found n matches, which is faster but not necessarily the nearest).
  • WITHDIST, WITHCOORD and WITHHASH add the distance, the position, and the raw score to each result.

GEOSEARCHSTORE writes the matches to another key, as a geospatial set or, with STOREDIST, as a sorted set scored by distance.

The older GEORADIUS and GEORADIUSBYMEMBER commands (and their _RO read-only forms) still work for existing code.

  • Longitudes run from -180 to 180. Latitudes are limited to the range -85.05112878 to 85.05112878, as in Redis: positions closer to the poles are refused.
  • Positions are stored at a fixed precision of well under a meter, so GEOPOS returns values that differ slightly from what you added.
  • Distances treat the Earth as a sphere, which can be off by up to about 0.5% compared with the true ellipsoid. That is fine for “nearby” searches but not for surveying.

Store locator. One key per brand or region, one member per store ID, details in a hash per store. GEOSEARCH ... FROMLONLAT <user position> BYRADIUS 10 km ASC COUNT 20 WITHDIST lists the nearest twenty.

Moving objects. Re-run GEOADD with each position update for drivers or vehicles, and ZREM them when they go offline. Searches always see the latest position.

Nearby, but only some members. Search with GEOSEARCHSTORE into a temporary key, then intersect it with a set of matching IDs using ZINTERSTORE, or filter the results in your application.

A time to live applies to the whole key; single places cannot expire. To drop stale positions, keep a separate sorted set of “last seen” times and remove members from both keys.

Command What it does
GEOADD Add or move members
GEODIST Distance between two members
GEOPOS Stored positions of members
GEOHASH Geohash strings of members
GEOSEARCH Members within a radius or box
GEOSEARCHSTORE Store search results in a key
GEORADIUS / GEORADIUS_RO Older radius search around a point
GEORADIUSBYMEMBER / GEORADIUSBYMEMBER_RO Older radius search around a member
import hotkv
client = hotkv.HotKV(host="localhost", port=6379, decode_responses=True)
client.geoadd("cities", {
"vienna": (16.3738, 48.2082),
"bratislava": (17.1077, 48.1486),
})
print(client.geodist("cities", "vienna", "bratislava", unit="km"))
nearby = client.geosearch("cities", longitude=16.5, latitude=48.2,
radius=100, unit="km", sort="ASC", withdist=True)
print(nearby)
client.close()

To use the geospatial commands from the Go client, send GEOADD, GEOSEARCH and the rest through a pipeline’s Do.