Geocoding and coordinates are a common use case in modern applications. These computations can be very heavy in terms of lookups so it is often desired to cache. Thus, Redis provides us with the geo data type to make using coordinates easy. In this article, we will learn how to use the Geo Data Type in Redis with Python.
For setting up Redis, I would recommend using a service for you in prod. Azure for example, has a great redis service that scales easily. However, you will want to learn redis and eventually how to scale it yourself. This will help with debugging cloud services or eventually, saving money and not using them.
We will start our intro to redis via using docker compose. Create a docker-compose.yml
file and add the following.
version: "3.2"
services:
redis:
image: "redis:alpine"
command: redis-server
ports:
- "6379:6379"
volumes:
- $PWD/redis-data:/var/lib/redis
- $PWD/redis.conf:/usr/local/etc/redis/redis.conf
environment:
- REDIS_REPLICATION_MODE=master
Ensure you have docker installed and run
docker-compose up
In python, the main used redis module is called redis-py
and can be installed using the follows.
pip install redis
Let's open up a new file, index.py
and go through many of
the common commands you will used with lists in redis.
We can add items to a geo set using the following. The example below will create a Geo Set called Sicilty that is a sorted set. We will then add Palermo then add Catania with their respective longitude and latitude.
# Geo Add
r.geoadd("Sicily", 13.361389, 38.115556, "Palermo")
r.geoadd("Sicily", 15.087269, 37.502669, "Catania")
For each of the examples below, I will use the following template to run all the commands. Here is my full index file. We will just replace the commands each time.
import redis
r = redis.Redis(host='localhost', port=6379, db=0)
# Geo Add
r.geoadd("Sicily", 13.361389, 38.115556, "Palermo")
r.geoadd("Sicily", 15.087269, 37.502669, "Catania")
Once we have a geo set, we can start to do calulcations on it. For example, we can get the distance between two members using the following.
# Geo Dist
const result = r.geodist("Sicily", "Palermo", "Catania")
print(result) # 166274.1516
We can also get all items within a radius using the georadius
command.
# Geo Radius - key for geo hash, long, latitude, radius, unit
const result = r.georadius("Sicily", 15, 27, 200, "km")
print(result) # 2
If we would like to get the specific hash for our geo sets, we can use geohash
# Geo Hash
const result = r.geohash("Sicily", "Palermo", "Catania")
print(result) # [ 'sqc8b49rny0', 'sqdtr74hyu0' ]
The geopos
class will return the position of members in our geo hash.
# Geo Position
const result = r.geopos("Sicily", "Palermo", "Catania", "Random")
print(result)
# [
# [ '13.36138933897018433', '38.11555639549629859' ],
# [ '15.08726745843887329', '37.50266842333162032' ],
# null
# ]
To get the distance between two members, we can use the geodist
command. We have the option to specificy the units.
# Geo Distance
const result = r.geodist("Sicily", "Palermo", "Catania")
print(result) # 166274.1516
const result2 = r.geodist("Sicily", "Palermo", "Catania", "km")
print(result2) # 166.2742
The geosearch
command provides an api to allow us to search the geo members of our set.
# Geo Search
const result = r.geosearch("Sicily", "FROMLONLAT", 15, 37, "BYRADIUS", 200, "km", "ASC")
print(result) # [ 'Catania', 'Palermo' ]