Redis – Indices Geoespaciales

Los índices geoespaciales de Redis almacenan puntos (nombres asociados a coordenadas: latitud y longitud), que al ser almacenados en memoria, son rápidamente actualizables y apropiados para mostrar la localización en tiempo real de personas, vehículos, o cualquier elemento que pueda cambiar su posición, y permiten ejecutar consultas geoespaciales (ej: distancia entre dos puntos, restaurantes cercanos en un radio determinado, etc).

Continuando con nuestra serie sobre Redis, ahora que ya hemos hablado sobre las diferentes estructuras de datos que soporta Redis (Strings, Hashes, Lists, Sets, y Sorted Sets), del problema y posibles soluciones de la búsqueda sobre claves en función de sus Atributos, las Transacciones en Redis, y el mecanismo de Publicación y Suscripción en Redis, llega el momento de los índices geoespaciales.

Un índice geoespacial, es una clave (Key) que está formada por tuplas que contienen un nombre único o ID, la latitud, y la longitud, sobre el que podremos añadir tuplas con el comando GEOADD. Cada pareja de valores de latitud y longitud, Redis calcula un GeoHash (un entero de 52 bits), un estandar que favorece un almacenamiento más compacto así como faciliata las posteriores consultas (cuanto más parecidos son los primeros dígitos de dos GeoHash, es que son dos puntos más próximos, e igualmente se puede acortar por la derecha produciendo una pérdida de precisión). De este modo, un índice geoespacial es almacenado en Redis como un Sorted Set, donde la puntuación (score) es el GeoHash y el valor asociado es el nombre único o ID del punto (consultable con el comando ZRANGE, por ejemplo, siendo posible utilizar todos los comandos de Sorted Sets, realizar operaciones de conjuntos como las intersecciones, etc).

  • El comando GEOHASH devuelve el valor GeoHash de uno o varios miembros de un índice geoespacial, en una representación alfanumérica de 11 caracteres.
  • El comando GEOPOS devuelve la latitud y longitud de uno o varios miembros de un índice geoespacial
  • El comando ZREM es el que utilizaremos para eliminar un miembro de un índice geoespacial, accediendo directamente al Sorted Set.

Redis ofrece tres comandos para consultar indices geoespaciales:

  • El comando GEODIST calcula la distancia entre dos miembros de un índice geoespacial, sea en metros, kilómetros, pies, o millas.
  • El comando GEORADIUS permite hacer una búsqueda de proximidad utilizando como referencia una posición (ej: nuestra posición actual), acotado a un radio determinado (ej: 3 KM). Este comando devuelve un conjunto de resultados sin orden, por lo que podemos utilizar argumentos adicionales, que nos permiten indicar el orden, o pedir que nos muestre la distancia a cada punto, o sus coordenadas. También podemos limitar el número de resultados, por ejemplo, a un TOP3 para tener sólo los más cercanos. También permite almacenar el resultado de la búsqueda en otra clave.
  • El comando GEORADIUSBYMEMBER permite hacer una búsqueda de proximidad utilizando como referencia la posición de uno de los miembros del índice, acotado a un radio determinado. Por ejemplo, podríamos consultar los restaurantes en un radio de 5km tomando como referencia otro restaurante, y así ver la densidad de los mismos. Es similar al comando anterior (GEORADIUS).

Es habitual complementar los indices geoespaciales con estructuras de datos adicionales, habitualmente con un Hash. De este modo, podríamos tener un índice geoespacial de restaurantes que almacena sólamente su posición, y un Hash de restaurantes que almacena el resto de datos de cada restaurante.

GEOADD restaurantes:hard-rock 36.720274850852796 -4.412837513870754 hard-rock-malaga
GEOADD restaurantes:hard-rock 37.38290580450277 -5.9927576013197905 hard-rock-sevilla
GEOADD restaurantes:hard-rock 39.4688961836124 -0.3772178625424107 hard-rock-valencia 41.38593769703032 2.170758251977237 hard-rock-barcelona

HSET restaurantes-detalle:hard-rock:hard-rock-malaga seats 112 hora-apertura 11:00 hora-cierra 1:00
HSET restaurantes-detalle:hard-rock:hard-rock-sevilla seats 131 hora-apertura 11:00 hora-cierra 1:00
HSET restaurantes-detalle:hard-rock:hard-rock-valencia seats 97 hora-apertura 11:30 hora-cierra 1:00
HSET restaurantes-detalle:hard-rock:hard-rock-barcelona seats 124 hora-apertura 11:00 hora-cierra 1:30

GEORADIUS restaurantes:hard-rock 41.38465141226809 2.1708466748801207 3 km
GEORADIUS restaurantes:hard-rock 41.38465141226809 2.1708466748801207 3000 km ASC
GEORADIUS restaurantes:hard-rock 41.38465141226809 2.1708466748801207 3000 km ASC WITHDIST
GEORADIUS restaurantes:hard-rock 41.38465141226809 2.1708466748801207 3000 km ASC WITHCOORD
GEORADIUS restaurantes:hard-rock 41.38465141226809 2.1708466748801207 3000 km ASC WITHDIST COUNT 3

GEODIST restaurantes:hard-rock hard-rock-malaga hard-rock-sevilla km

ZRANGE restaurantes:hard-rock 0 -1 WITHSCORES

GEOHASH restaurantes:hard-rock hard-rock-malaga
GEOPOS restaurantes:hard-rock hard-rock-malaga hard-rock-sevilla

A continuación se muestra el resultado de ejecución de los anteriores comandos en redis-cli.

Despedida y Cierre

Hasta aquí llega este Post, en el que hemos hecho una introducción a los índices geoespaciales en Redis, de gran utilidad en muchos casos de uso, como para obtener los puntos (ej: restaurantes) cerca de otro punto (ej: nuestra posición actual), obtener la distancia entre dos puntos, etc., y como podemos utilizar estructuras de datos adicionales como Hash para almacenar datos adicionales.

Poco más por hoy. Como siempre, confío que la lectura resulte de interés.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

cuatro + doce =