Redis Geospatial地理位置

Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。

Redis GEO 操作方法有:

  • geoadd:添加地理位置的坐标。
  • geopos:获取地理位置的坐标。
  • geodist:计算两个位置之间的距离。
  • georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
  • georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
  • geohash:返回一个或多个位置对象的 geohash 值。

geoadd:添加地理位置的坐标。

geoadd 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。南北两级无法添加。

平时,我们一般会直接下载城市数据,然后通过java程序导入。

经度范围是0-180°,纬度范围是0-90°。

1
2
3
4
5
 127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 121.47 31.23 shanghai
(integer) 2
1234

geopos:获取地理位置的坐标

geopos 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。

1
2
3
4
5
6
7
8
 127.0.0.1:6379> geopos china:city beijing shanghai
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
2) 1) "121.47000163793563843"
2) "31.22999903975783553"
127.0.0.1:6379> geopos china:city nanchang
1) (nil)
1234567

geodist:计算两个位置之间的距离

geodist 用于返回两个给定位置之间的距离,直线距离

最后一个距离单位参数说明:

  • m :米,默认单位。
  • km :千米。
  • mi :英里。
  • ft :英尺。
1
2
3
4
5
6
7
8
9
10
11
 127.0.0.1:6379> geodist china:city beijing chongqing   #北京和重庆之间的距离  默认单位m
"1464070.8051" #默认单位m
127.0.0.1:6379> geodist china:city beijing chongqing km
"1464.0708"
127.0.0.1:6379> geodist china:city beijing chongqing ft
"4803381.9063"
127.0.0.1:6379> geodist china:city beijing chongqing mi
"909.7337"
127.0.0.1:6379> geodist china:city beijing nanchang #,不存在的返回 nil
(nil)
12345678910

georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合

georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合

  • georadius 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。

  • georadiusbymember 和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 georadiusbymember 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。

  • 参数说明:

    • m :米,默认单位。
    • km :千米。
    • mi :英里。
    • ft :英尺。
    • WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
    • WITHCOORD: 将位置元素的经度和维度也一并返回。
    • WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
    • COUNT 限定返回的记录数。
    • ASC: 查找结果根据距离从近到远排序。
    • DESC: 查找结果根据从远到近排序,默认。

georadius 实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 #================返回以 119 35 中心,半径1000km内所有城市================
127.0.0.1:6379> GEORADIUS china:city 119 35 1000 km
1) "beijing"
2) "shanghai"
#================返回以 119 35 中心,半径1000km内所有城市,并将位置元素与中心之间的距离也一并返回================
127.0.0.1:6379> GEORADIUS china:city 119 35 1000 km withdist
1) 1) "beijing"
2) "591.3126"
2) 1) "shanghai"
2) "478.2625"
#================返回以 119 35 中心,半径1000km内所有城市,将位置元素的经度和维度也一并返回================
127.0.0.1:6379> GEORADIUS china:city 119 35 1000 km withcoord
1) 1) "beijing"
2) 1) "116.39999896287918091"
2) "39.90000009167092543"
2) 1) "shanghai"
2) 1) "121.47000163793563843"
2) "31.22999903975783553"
#返回以 119 35 中心,半径1000km内所有城市,将位置元素与中心之间的距离一并返回,将位置元素的经度和维度也一并返回
127.0.0.1:6379> GEORADIUS china:city 119 35 1000 km withcoord withdist
1) 1) "beijing"
2) "591.3126"
3) 1) "116.39999896287918091"
2) "39.90000009167092543"
2) 1) "shanghai"
2) "478.2625"
3) 1) "121.47000163793563843"
2) "31.22999903975783553"
#================================限定返回的记录数为1================================
127.0.0.1:6379> GEORADIUS china:city 119 35 1000 km count 1
1) "shanghai"
#================================查找结果根据距离从近到远排序================================
127.0.0.1:6379> GEORADIUS china:city 119 35 1000 km withdist asc
1) 1) "shanghai"
2) "478.2625"
2) 1) "beijing"
2) "591.3126"

1234567891011121314151617181920212223242526272829303132333435363738

georadiusbymember实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
 127.0.0.1:6379> GEOADD Sicily 13.583333 37.316667 "Agrigento"
(integer) 1
127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"
127.0.0.1:6379> GEORADIUSBYMEMBER Sicily Agrigento 100 km withdist
1) 1) "Agrigento"
2) "0.0000"
2) 1) "Palermo"
2) "90.9778"
123456789101112

geohash:返回一个或多个位置对象的 geohash 值。

  • Redis GEO 使用 geohash 来保存地理位置的坐标,
  • 将二维经纬度转化为一维字符串,如果两个字符串越接近,则两个位置越接近。
  • geohash 用于获取一个或多个位置元素的 geohash 值。
1
2
3
4
5
6
 127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
127.0.0.1:6379> GEOHASH Sicily Palermo Catania
1) "sqc8b49rny0"
2) "sqdtr74hyu0"
12345

geo底层实现原理其实就是zset,我们可以通过zset命令来操作geo

尝试用zset的查询指令,查询添加的GEO信息:

1
2
3
4
5
6
7
8
9
10
11
12
 127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 121.47 31.23 shanghai
(integer) 2
127.0.0.1:6379> zrange china:city 0 -1 withscores
1) "chongqing"
2) "4026042091628984"
3) "shanghai"
4) "4054803462927619"
5) "beijing"
6) "4069885360207904"
1234567891011

可以查到 “chongqing"的位置信息为"4026042091628984”, “shanghai"的位置信息为"4054803462927619”, “beijing"的位置信息为"4069885360207904”。

4026042091628984为对经纬度进行编码后的值。使用4026042091628984做为score 能够快速实现对经纬度的索引。

至此能够推断出Redis GEO 添加经、纬度位置信息的指令的过程是:

1
2
3
4
 ZADD china:city 4026042091628984 chongqing
ZADD china:city 4054803462927619 shanghai
ZADD china:city 4069885360207904 beijing
123

对数据进行删除:

1
2
3
4
5
6
127.0.0.1:6379> zrem china:city chongqing
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "shanghai"
2) "beijing"