23. Redis---地理位置
1.前言
在 Redis 3.2 版本中,新增了存储地理位置信息的功能,即 GEO(英文全称 geographic),它的底层通过 Redis 有序集合(zset)实现。不过 Redis GEO 并没有与 zset 共用一套的命令,而是拥有自己的一套命令。
Redis GEO 提供了 6 个常用命令:
- GEOADD
- GEOPOS
- GEODIST
- GEORADIUS
- GEORADIUSBYMEMBER
- GEOHASH
Redis GEO 有很多应用场景,举一个简单的例子,你一定点过外卖,或者用过打车软件,在这种 APP上会显示“店家距离你有多少米”或者“司机师傅距离你有多远”,类似这种功能就可以使用 Redis GEO 实现。数据库中存放着商家所处的经纬度,你的位置则由手机定位获取,这样 APP 就计算出了最终的距离。再比如微信中附近的人、摇一摇、实时定位等功能都依赖地理位置实现。
GEO 提供以下操作命令,如下表所示:
序号 | 命令 | 说明 |
---|---|---|
1 | GEOADD | 将指定的地理空间位置(纬度、经度、名称)添加到指定的 key 中。 |
2 | GEOPOS | 从 key 里返回所有给定位置元素的位置(即经度和纬度) |
3 | GEODIST | 返回两个地理位置间的距离,如果两个位置之间的其中一个不存在, 那么命令返回空值。 |
4 | GEORADIUS | 根据给定地理位置坐标(经纬度)获取指定范围内的地理位置集合。 |
5 | GEORADIUSBYMEMBER | 根据给定地理位置(具体的位置元素)获取指定范围内的地理位置集合。 |
6 | GEOHASH | 获取一个或者多个的地理位置的 GEOHASH 值。 |
7 | ZREM | 通过有序集合的 zrem 命令实现对地理位置信息的删除。 |
1) GEOADD
将指定的地理空间位置(纬度、经度、名称)添加到指定的 key 中。语法格式如下:
GEOADD key longitude latitude member [longitude latitude member ...]
- longitude:位置地点所处的经度;
- latitude:位置地点所处的纬度;
- member:位置名称。
将给定的经纬度的位置名称(纬度、经度、名字)与 key 相对应,这些数据以有序集合的形式进行储存。GEOADD
命令以标准的x,y
形式接受参数, 所以用户必须先输入经度,然后再输入纬度。GEOADD
命令能够记录的坐标数量是有限的,如果位置非常接近两极(南极/北极)区域,那么将无法被索引到。因此当您输入经纬度时,需要注意以下规则:
- 有效的经度介于 -180 度至 180 度之间。
- 有效的纬度介于 -85.05112878 度至 85.05112878 度之间。
注意:如果您输入一个超出范围的经纬度时,GEOADD 命令将返回一个错误。
示例演示如下:
#添加城市地理位置
127.0.0.1:6379> geoadd city 116.20 39.56 beijing 120.52 30.40 shanghai
(integer) 2
#查询城市地理位置
127.0.0.1:6379> GEOPOS city beijing shanghai
1) 1) "116.19999736547470093"
2) "39.56000019952067248"
2) 1) "120.52000075578689575"
2) "30.39999952668997452"
2) GEODIST
该命令用于获取两个地理位置间的距离。返回值为双精度浮点数,其语法格式如下:
GEODIST key member1 member2 [unit]
参数 unit 是表示距离单位,取值如下所示:
- m 表示单位为米;
- km 表示单位为千米;
- mi 表示单位为英里;
- ft 表示单位为英尺。
注意:如果没有指出距离单位,那么默认取值为m
。示例如下:
127.0.0.1:6379> GEODIST city beijing shanghai
"1091868.8970"
127.0.0.1:6379> GEODIST city beijing shanghai km
"1091.8689"
127.0.0.1:6379> GEODIST city beijing shanghai mi
"678.4576"
注意:计算举例时存在 0.5% 左右的误差,这是由于 Redis GEO 把地球假设成了完美的球体。
3) GEORADIUS
以给定的经纬度为中心,计算出 key 包含的地理位置元素与中心的距离不超过给定最大距离的所有位置元素,并将其返回。
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]
参数说明:
- WITHDIST :在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
- WITHCOORD :返回位置元素的经度和维度。
- WITHHASH :采用 GEOHASH 对位置元素进行编码,以 52 位有符号整数的形式返回有序集合的分值,该选项主要用于底层调试,实际作用不大。
- COUNT:指定返回位置元素的数量,在数据量非常大时,可以使用此参数限制元素的返回数量,从而加快计算速度。
注意:该命令默认返回的是未排序的位置元素。通过 ASC 与 DESC 可让返回的位置元素以升序或者降序方式排列。
命令应用示例如下:
#添加几个地理位置元素
127.0.0.1:6379> GEOADD city 106.45 29.56 chongqing 120.33 36.06 qingdao 103.73 36.03 lanzhou
(integer) 3
127.0.0.1:6379> GEOADD city 106.71 26.56 guiyang
(integer) 1
#以首都的坐标为中心,计算各个城市距离首都的距离,最大范围设置为1500km
#同时返回距离,与位置元素的经纬度
127.0.0.1:6379> GEORADIUS city 116.41 39.91 1500 km WITHCOORD WITHDIST
1) 1) "chongqing"
2) "1465.5618"
3) 1) "106.4500012993812561"
2) "29.56000053864853072"
2) 1) "lanzhou"
2) "1191.2793"
3) 1) "103.72999995946884155"
2) "36.03000049919800318"
3) 1) "shanghai"
2) "1121.4882"
3) 1) "120.52000075578689575"
2) "30.39999952668997452"
4) 1) "qingdao"
2) "548.9304"
3) 1) "120.3299984335899353"
2) "36.05999892411877994"
5) 1) "beijing"
2) "42.8734"
3) 1) "116.19999736547470093"
2) "39.56000019952067248"
4) GEORADIUSBYMEMBER
根据给定的地理位置坐标(即经纬度)获取指定范围内的位置元素集合。其语法格式如下:
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DES]
- m :米,默认单位;
- km :千米(可选);
- mi :英里(可选);
- ft :英尺(可选);
- ASC:根据距离将查找结果从近到远排序;
- DESC:根据距离将查找结果从远到近排序。
该命令与 GEORADIUS 命令相似,不过它选择的中心的是具体的位置元素,而非经纬度坐标。示例如下:
#以贵阳为中心,最大距离不超过900km
127.0.0.1:6379> GEORADIUSBYMEMBER city guiyang 900 km WITHCOORD WITHDIST
1) 1) "guiyang"
2) "0.0000"
3) 1) "106.70999854803085327"
2) "26.56000089385899798"
#只有重庆符合条件
2) 1) "chongqing"
2) "334.6529"
3) 1) "106.4500012993812561"
2) "29.56000053864853072"
5) GEOHASH
返回一个或多个位置元素的哈希字符串,该字符串具有唯一 ID 标识,它与给定的位置元素一一对应。示例如下:
127.0.0.1:6379> GEOHASH city lanzhou beijing shanghai
1) "wq3ubrjcun0"
2) "wx49h1wm8n0"
3) "wtmsyqpuzd0"
6) ZREM
用于删除指定的地理位置元素,示例如下:
127.0.0.1:6379> zrem city beijing shanghai
(integer) 2
了解更多命令请参考:http://redisdoc.com/geo/geohash.html