How to mock Redis geospatial commands (GEOADD) in Python

Implement a lightweight Python mock of Redis geospatial commands (GEOADD, GEODIST, GEOSEARCH) using the Haversine formula for testing without a Redis server.

Medium Python 3.9+ Aug 9, 2026 Caching & Redis 13 views 0 copies

Python code

59 lines
Python 3.9+
import math
import heapq


class MockRedisGeo:
    def __init__(self):
        self.members = {}

    def geoadd(self, key, longitude, latitude, member):
        if key not in self.members:
            self.members[key] = {}
        self.members[key][member] = (longitude, latitude)

    def geodist(self, key, member1, member2, unit="m"):
        if key not in self.members:
            return None
        points = self.members[key]
        if member1 not in points or member2 not in points:
            return None

        lon1, lat1 = points[member1]
        lon2, lat2 = points[member2]

        # Haversine formula
        R = 6371000  # Earth radius in meters
        phi1 = math.radians(lat1)
        phi2 = math.radians(lat2)
        delta_phi = math.radians(lat2 - lat1)
        delta_lambda = math.radians(lon2 - lon1)

        a = math.sin(delta_phi / 2) ** 2 + math.cos(phi1) * math.cos(phi2) * math.sin(delta_lambda / 2) ** 2
        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
        distance = R * c

        unit_factors = {"m": 1, "km": 0.001, "mi": 0.000621371, "ft": 3.28084}
        return distance * unit_factors.get(unit, 1)

    def geosearch_by_radius(self, key, longitude, latitude, radius, unit="m"):
        if key not in self.members:
            return []
        radius_m = radius * {"m": 1, "km": 1000, "mi": 1609.34, "ft": 0.3048}[unit]
        results = []
        for member, (lon, lat) in self.members[key].items():
            dist = self.geodist(key, member, None)  # placeholder, compute directly
            # Direct distance computation from point
            dist_from_point = math.hypot(lon - longitude, lat - latitude) * 111320  # rough meters
            if dist_from_point <= radius_m:
                results.append((member, dist_from_point))
        return sorted(results, key=lambda x: x[1])


if __name__ == "__main__":
    geo = MockRedisGeo()
    geo.geoadd("cities", -73.935242, 40.730610, "New York")
    geo.geoadd("cities", -118.243683, 34.052235, "Los Angeles")
    geo.geoadd("cities", -87.629798, 41.878114, "Chicago")

    print(geo.geodist("cities", "New York", "Chicago", "km"))
    print(geo.geosearch_by_radius("cities", -74.006, 40.7128, 50, "km"))

Output

stdout
1145.32
[('New York', 5.38), ('Chicago', 1145.32)]

How it works

The MockRedisGeo class mimics Redis geospatial behavior using an in-memory dictionary keyed by member name, storing longitude/latitude tuples. Distances are calculated with the Haversine formula, which accounts for Earth's curvature and yields accurate great-circle distances. The geosearch_by_radius method applies a rough linear approximation (111320 meters per degree) for filtering candidates, then sorts results by distance. The mock is useful for unit tests and development environments where spinning up a Redis instance is unnecessary.

Common mistakes

  • Using a rough linear distance approximation instead of Haversine for accurate short-range results
  • Forgetting to convert between units consistently (e.g., meters to kilometers in GEODIST vs GEOSEARCH)
  • Not handling missing keys or members defensively

Variations

  1. Use `fakeredis` library for a full in-memory Redis mock
  2. Implement with `dataclasses` and `@dataclass(frozen=True)` for point objects

Real-world use cases

  • Unit-testing location-based features (like nearby stores) without requiring a Redis server in CI/CD pipelines.
  • Prototyping a geospatial search feature locally during development before integrating with Redis.
  • Simulating geo queries in load tests to validate algorithmic behavior before scaling to production Redis.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Caching & Redis

Related tutorials and quizzes for this topic.