Redis GEO 相关命令简介

Redis GEO 特性(Redis版本>=3.2.0)支持对地理位置进行存储、空间索引、空间查询等相关操作。下面简要介绍其基本命令。

使用 GEOADD 添加位置

GEOADD 用于将给定的地理空间元素(纬度、经度、名称)添加到指定的集合(由key指定)中。Redis 内部会把对应的数据存储到一个 zset 有序集合中。存储时经纬度坐标会转换为 Geohash 值以实现空间索引,从而支持空间查询操作。

命令形式

1
GEOADD key longitude latitude member [longitude latitude member ...]

GEOADD 命令以 x,y 的格式接受经纬度参数,即经度在前,纬度在后。可以一次添加多个地理位置信息,即纬度、经度、名称可以重复多次。

GEOADD 支持的坐标范围是有限的,接近两极的坐标无法支持:

  • 有效的经度介于 -180 度至 180 度之间。
  • 有效的纬度介于 -85.05112878 度至 85.05112878 度之间。

GEOADD 每添加一个元素的时间复杂度为 O(log(N)) ,其中 N 为 key 对应的集合中的元素数量。

GEOADD 命令的返回值为新加入到集合中的地理空间元素的数量,集合中已存在的的元素(仅更新)不计入内。

示例

1
2
3
4
5
6
7
8
9
10
11
12
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEODIST Sicily Palermo Catania
"166274.15156960039"

redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"

redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"

使用 GEOPOS 获取位置

GEOPOS 用于从集合中获取指定元素的地理位置。

命令形式

1
GEOPOS key member [member ...]

GEOPOS 命令一次可指定多个元素,因此即使用户仅查询一个元素,该命令返回的也是数组。

返回的数组中,每项都由两个元素组成:第一个元素表示经度,而第二个元素表示纬度。当给定的位置元素不存在时,对应的数组项为空值。

GEOPOS 命令每查询一个元素的位置对应的时间复杂度为 O(log(N)) ,其中 N 是 key 对应的集合中的元素数量。

注意:由于存储的时候经纬度坐标被转换为 52位的 Geohash 值,因此存取过程中会引入误差,取回的经纬度可能和设置时的值略有差异。

示例

1
2
3
4
5
6
7
8
9
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "15.087267458438873"
2) "37.50266842333162"
3) (nil)

使用 GEODIST 计算距离

GEODIST 命令可以计算集合中两个元素地理上的距离。

命令形式

1
GEODIST key member1 member2 [unit]

指定单位的参数 unit 必须是以下单位的其中一个:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

如果没有指定单位,默认使用米作为单位。

计算得到的距离会以 double 值返回。如果给定的位置元素不存在,将返回空值。

使用 GEODIST 计算集合中两个元素的距离对应的时间复杂度为 O(log(N))

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEODIST Sicily Palermo Catania
"166274.15156960039"

redis> GEODIST Sicily Palermo Catania km
"166.27415156960038"

redis> GEODIST Sicily Palermo Catania mi
"103.31822459492736"

redis> GEODIST Sicily Foo Bar
(nil)

使用 GEORADIUS 或 GEORADIUSBYMEMBER 获取指定范围内的元素

GEORADIUS 和 GEORADIUSBYMEMBER 命令都可以用来查找指定范围内的元素。两者的不同在于指定中心点的方式。

命令形式

下面分别介绍 GEORADIUS 和 GEORADIUSBYMEMBER 的使用。

GEORADIUS

1
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]

GEORADIUS 命令以给定的经纬度为中心,在 key 对应的集合中查找距离该中心位置不超过 radius 指定的最大距离的所有元素。

支持的距离单位如下:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

GEORADIUS 命令的时间复杂度为 O(N+log(M)), 其中 N 为指定半径范围的边界矩形内的元素数量,而 M 则是集合中元素的数量。

GEORADIUS 命令返回的一个数组,在没有 WITH 选项时返回的是一个简单的线性表,在指定了 WITHCOORD, WITHDIST, WITHHASH 等选项时, 返回的一个嵌套数组,内层的每个子数组表示一个元素。

选项
  • WITHCOORD:同时返回元素的经纬度
  • WITHDIST:同时返回元素离中心点的距离
  • WITHHASH:同时返回 geohash 编码
  • ASC:按离中心点距离由近到远排序
  • DESC:按离中心点距离由远到近排序
  • COUNT count:仅返回指定数量的元素,在范围内元素过多的时候,可以减少返回的元素,提高效率。

GEORADIUSBYMEMBER

1
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]

GEORADIUSBYMEMBER 命令和 GEORADIUS 命令一样,都是用来查找指定范围内的元素,不同的是 GEORADIUSBYMEMBER 的中心点是给定的集合中的元素对应的地理位置。

示例

下面分别举例说明 GEORADIUS 和 GEORADIUSBYMEMBER 的用法。

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
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEORADIUS Sicily 15 37 200 km WITHDIST
1) 1) "Palermo"
2) "190.4424"
2) 1) "Catania"
2) "56.4413"

redis> GEORADIUS Sicily 15 37 200 km WITHCOORD
1) 1) "Palermo"
2) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "Catania"
2) 1) "15.087267458438873"
2) "37.50266842333162"

redis> GEORADIUS Sicily 15 37 200 km WITHDIST WITHCOORD
1) 1) "Palermo"
2) "190.4424"
3) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "Catania"
2) "56.4413"
3) 1) "15.087267458438873"
2) "37.50266842333162"

GEORADIUSBYMEMBER

1
2
3
4
5
6
7
8
9
redis> GEOADD Sicily 13.583333 37.316667 "Agrigento"
(integer) 1

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"

使用 GEOHASH 获取 Geohash 表示

GEOHASH 命令用于获取集合中一个或多个元素的 Geohash 表示。

命令形式

1
GEOHASH key member [member ...]

GEOHASH 命令返回的是一个数组, 数组的每个项都是一个 geohash 。 命令返回的 geohash 的位置与用户给定的元素位置一一对应。

GEOHASH 命令获取每个元素的 Geohash 的时间复杂度为 O(log(N))

示例

1
2
3
4
5
6
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEOHASH Sicily Palermo Catania
1) "sqc8b49rny0"
2) "sqdtr74hyu0"

参考资料

https://redis.io/commands/geoadd

https://redis.io/commands/geodist

https://redis.io/commands/geopos

https://redis.io/commands/geohash

https://redis.io/commands/georadius