Redis数据结构之地理坐标
Redis地理坐标
Redis GEO是Redis 在3.2版本中新添加的特性,通过这一特性,用户可以将经纬度格式的地理坐标存储到Redis中,并对这些坐标执行距离计算,范围查找等操作。
地理坐标的功能
Redis为GEO特性提供了一系列命令,具体如下所示:
- 将位置的名字以及它的经纬度存储到位置集合中。
- 根据给定的位置名字,从位置集合中取出与之对应的经纬度。
- 计算两个位置之间的直线距离。
- 根据给定的经纬度或位置,找出该位置指定的半径范围内的其他位置。
- 获取指定位置的Geohash编码。
地理坐标命令速查表
下表列出了地理坐标的命令、用法参数及说明:
命令 | 用法及参数 | 说明 |
---|---|---|
GEOADD | GEOADD location_set longitude latitude name [longitude latitude name ...] | 将一个或多个经纬度坐标存储到集合中,并设置相应的名字 |
GEOPOS | GEOPOS location_set name [name ...] | 获取一个或多个给定位置的坐标 |
GEODIST | GEODIST location_set name1 name2 [unit] | 计算两个给定位置的直线距离,unit可以用来指定距离单位,默认为米 |
GEORADIUS | GEORADIUS location_set longitude latitude radius unit | 以给定的坐标为圆心,从位置集合中找出位于中心点指定半径范围内的其他位置 |
GEORADIUSBYMEMBER | GEORADIUSBYMEMBER location_set name radius unit [WITHDIST] [WITHCOORD] [COUNT n] [ASC|DESC] | 查找指定位置半径范围内的其他位置 |
GEOHASH | GEOHASH key member [member ...] | 获取一个或多个位置对应的经纬度坐标的Geohash |
命令详解
GEOADD命令
使用GEOADD命令,可以将给定的一个或多个经纬度坐标存储到位置集合中,并设置相应的名字:
GEOADD location_set longitude latitude name [longitude latitude name ...]
GEOADD命令会返回新添加的坐标数量作为返回值,如果给定的位置在集合中已经有了与之关联的坐标,则将更新该坐标。
复杂度:
O
(
l
o
n
g
(
N
)
∗
M
)
O(long(N)*M)
O(long(N)∗M),其中
N
N
N为位置集合目前包含的位置数量,
M
M
M为用户给定的位置数量。
版本要求:GEOADD命令从Redis 3.2.0版本开始可用。
GEOPOS命令
使用GEOPOS命令可以获取一个或多个给定位置的坐标:
GEOPOS location_set name [name ...]
GEOPOS命令会返回一个数组作为结果,每个元素代表一个位置的坐标。
复杂度:
O
(
l
o
g
(
N
)
∗
M
)
O(log(N)*M)
O(log(N)∗M),其中
N
N
N为集合中包含的位置数量,而
M
M
M为用户给定的位置数量。
版本要求:GEOPOS命令从Redis 3.2.0版本开始可用。
GEODIST命令
使用GEODIST命令可以用来计算两个给定位置的直线距离:
GEODIST location_set name1 name2
在默认情况下,GEODIST命令将以米为单位,返回两个值位置之间的直线距离。
指定距离单位
GEODIST命令默认使用米作为单位,用户也可以在有需要的情况下,通过可选的unit参数指定自己想要使用的单位:
GEODIST location_set name1 name2 [unit]
unit参数的值可以是以下单位中的任意一个:
- m——以米为单位,默认单位。
- km——以千米为单位。
- mi——以英里为单位。
- ft——以英尺为单位。
当给定的某个位置不存在与集合中式,将返回空值(nil)表示失败。
复杂度:
O
(
l
o
g
(
N
)
)
O(log(N))
O(log(N)),其中
N
N
N为位置集合目前包含的位置数量。
版本要求:GEODIST命令从 Redis 3.2.0版本开始可用。
GEORADIUS命令
通过使用GEORADIUS命令可以指定一个经纬度作为中心点,并从位置集合中找出位于中心点指定半径范围内的其他位置:
GEORADIUS location_set longitude latitude radius unit
各个命令参数意义如下:
- location_set 指定的位置集合。
- longitude 和 latitude用于指定中心点的经纬度。
- radius 指定查找半径。
- unit 指定查找半径的单位。
返回匹配位置与中心点之间的距离
GEORADIUS命令具有可选的WITHDIST选项,可以用来返回查找到的匹配位置与中心点之间的距离:
GEORADIUS location_set longitude latitude radisu unit [WITHDIST]
WITHDIST所使用的单位也是根据unit参数指定的为准。
返回匹配位置的坐标
除了WITHDIST以外,GEORADIUS命令还提供了另一个可选项 WITHCOORD,可以用来返回匹配位置的坐标:
GEORADIUS location_set longitude latitude radius unit [WITHCOORD]
排序查找结果
GEORADIUS命令在默认情况下会以无序方式返回被匹配的位置,但是通过使用可选的ASC选项或DESC选项,可以指定以升序或降序的方式返回结果:
GEORADIUS location_set longitude latitude radius unit [ASC|DESC]
指定返回的位置数量
默认情况下,GEORADIUS会返回所有匹配到的位置,通过可选项 COUNT可以指定返回的最大位置数:
GEORADIUS location_set longitude latitude radius unit [COUNT n]
复杂度:
O
(
N
)
O(N)
O(N),其中
N
N
N为命令实施范围查找时检查的位置数量。
版本要求:从Redis 3.2.0开始可用。
GEORADIUSBYMEMBER命令
与GEORADIUS命令的作用一样,都是用来查找指定半径范围内的其他位置,区别在于:GEORADIUS是通过指定的经纬度来确定中心点的位置,而GEORADIUSBYMEMBER是通过选择一个集合中的位置作为中心点:
GEORADIUS location_set name radius unit [WITHDIST] [WITHCOORD] [COUNT n] [ASC|DESC]
参数与GEORADIUS命令的用法一支。
复杂度:
O
(
N
)
O(N)
O(N),其中
N
N
N为查找时检查的位置数量。
版本要求:从Redis 3.2.0开始可用。
GEOHASH命令
用户可以通过GEOHASH命令传入一个或多个位置来获得这些位置对应的经纬度坐标的Geohash表示:
GEOHASH key member [member ...]
GEOHASH是一种编码格式,这种格式可以将用户给定的经度和纬度转换成单个GeoHash值,也可以根据给定的GeoHash值还原出被转换的经度和纬度。
在进行范围查找时获取GeoHash值
GEORADIUS命令和GEORADIUSBYMEMBER命令都支持WITHHASH选项,使用这个选项时,命令将会在结果中包含被匹配位置的Geohash值:
GEORADIUS location_set longitude latitude radius unit [WITHHASH]
GEORADIUSBYMEMBER location_set name radius unit [WITHHASH]
需要注意的是: 与GEOHASH命令不一样,GEORADIUS命令和GEORADIUSBYMEMBER命令返回的是被解释为数字的GeoHash值,而GEOHASH命令返回的是被解释为字符串的GeoHash值。
复杂度:
O
(
N
)
O(N)
O(N),其中
N
N
N为用户给定的位置数量。
版本要求:GEOHASH命令从Redis 3.2.0版本开始可用。
使用有序集合命令操作GEO数据
Redis使用有序集合存储GEO数据,一个位置集合实际上就是一个有序集合:当用户调用GEO命令对位置集合进行操作时,这些命令实际上是在操作一个有序集合。
在使用GEOADD命令添加一个位置的时候,Redis会将位置坐标转化为GeoHash值,然后作为有序集合成员的分值存储起来。除了GEOADD命令以外,其他的几个命令同样都是在有序集合的基础上实现的。因此,我们可以使用有序集合的命令来操作地理坐标。
127.0.0.1:6379> ZRANGE Guangdong-cities 0 -1 WITHSCORES
1) "Zhongshan"
2) "4046330600091985"
还可以使用ZCARD命令来获取当位置集合中的位置数量:
127.0.0.1:6379> ZCARD Guangdong-cities
(integer) 1
还可以使用ZSCORE命令来获取指定位置的GeoHash值:
127.0.0.1:6379> ZSCORE Guangdong-cities "Zhongshan"
"4046330600091985"