在Redis中,在有序集合以及GeoHash的基础上实现了Geo类型表示地理空间信息。GeoHash是将经纬度进行编码,使二维信息变为一维信息的一种算法。下面我们就来介绍Redis中Geo类型相关的命令。
GEOADD
GEOADD
命令用于向Geo类型中添加一个或多个坐标元素,并返回新添加元素个数。若元素已存在(以member
参数指定的元素名称作为唯一性判断),则返回值将不包括该元素,但会更新其值。
GEOADD key longitude latitude member [longitude latitude member ...]
在添加时,其经纬度必须符合以下条件:
- -180 <= longitude <= 180
- -85.05112878 <= latitude <= 85.05112878
示例
redis> GEOADD buildings 121.5056 0 ShanghaiTower
(integer) 1
redis> GEOPOS buildings ShanghaiTower
1) 1) "121.50559991598129272"
2) "0.00000126736058093"
redis> GEOADD buildings 121.5056 31.2335 ShanghaiTower 121.4453 31.2235 JinganTemple
# ShanghaiTower已经存在,返回值将不包括它,但会更新其值
(integer) 1
redis> GEOPOS buildings ShanghaiTower
1) 1) "121.50559991598129272"
2) "31.23349948967888423"
# 不合法的坐标值
redis> GEOADD buildings 1000 500 Unknown
(error) ERR invalid longitude,latitude pair 1000.000000,500.000000
GEODIST
GEODIST
命令用于获取两个由GEOADD
添加的元素的距离,并表示为参数所指定的距离单位。当其中一个不存在或两个元素都不存在的情况下,将返回nil
。
GEODIST key member1 member2 [m|km|ft|mi]
GEODIST
命令可使用参数设置其距离的单位,允许的值为:
m
: 米km
: 千米ft
: 英尺mi
: 英里
在未设置的情况下,默认使用米作为单位。
示例
redis> GEOADD buildings 121.5056 31.2335 ShanghaiTower 121.4453 31.2235 JinganTemple
(integer) 2
redis> GEODIST buildings ShanghaiTower JinganTemple
"5842.1340"
redis> GEODIST buildings ShanghaiTower JinganTemple km
"5.8421"
redis> GEODIST buildings ShanghaiTower JinganTemple ft
"19167.1062"
redis> GEODIST buildings ShanghaiTower JinganTemple mi
"3.6301"
# 不存在的元素
redis> GEODIST buildings ShanghaiTower NoExists
(nil)
GEOHASH
GEOHASH
命令用于获取一个或多个由GEOADD
添加元素对应的GeoHash值,并以数组的形式返回。当其中某个元素不存在时,对应的位置将返回nil
。
GEOHASH key member [member ...]
命令返回以11个字符表示的GeoHash字符串值,可以通过http://geohash.org/<geohash-string>
查询对应的地理位置。关于GeoHash的具体信息,可参考GeoHash - Wikipedia。
示例
redis> GEOADD buildings 121.5056 31.2335 ShanghaiTower 121.4453 31.2235 JinganTemple
(integer) 2
redis> GEOHASH buildings ShanghaiTower
1) "wtw3svvsmd0"
redis> GEOHASH buildings ShanghaiTower JinganTemple NoExists
1) "wtw3svvsmd0"
2) "wtw3es1f0d0"
3) (nil) # 不存在
GEOPOS
GEOPOS
命令用于获取一个或多个由GEOADD
添加元素的坐标,并以(经度,纬度)
形式的二维数组返回。当其中某个元素不存在时,对应的位置将返回nil
。
GEOPOS key member [member ...]
示例
redis> GEOADD buildings 121.5056 31.2335 ShanghaiTower 121.4453 31.2235 JinganTemple
(integer) 2
redis> GEOPOS buildings ShanghaiTower
1) 1) "121.50559991598129272"
2) "31.23349948967888423"
# 获取多个
redis> GEOPOS buildings ShanghaiTower JinganTemple NoExists
1) 1) "121.50559991598129272"
2) "31.23349948967888423"
2) 1) "121.44529849290847778"
2) "31.22350001470528724"
3) (nil) # 不存在
GEORADIUS
GEORADIUS
命令用于获取以指定坐标位置为中心范围内小于指定距离的位置,其返回的结果需要为GEOADD
命令添加的元素。GEORADIUS
命令需要指定的参数依次为键名、中心点的经度、中心点的纬度、范围半径以及范围半径的单位。与GEODIST
支持的单位相同,GEORADIUS
也支持米、千米、英尺、英里四种距离单位。
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
GEORADIUS
命令支持使用下面三个参数获取除元素名称外的信息:
WITHCOORD
: 返回经纬度坐标。WITHDIST
: 返回距离中心点的距离。WITHHASH
: 返回GeoHash对应的整数值。
以上三个参数可以根据需要任意使用,也可以进行组合使用。当使用一个以上上述参数时,将会以下面的顺序在数组中返回:
- 距离中心点的距离。
- GeoHash值。
- 经纬度坐标
GEORADIUS
支持通过COUNT
参数指定返回的个数,以及使用ASC
或DESC
指定返回的顺序。当使用ASC
时,将以距离由近到远的顺序返回,而使用DESC
时将以距离由远到近的顺序返回,在未指定默认情况下,返回结果将以从近到远的顺序排列。
另外,GEORADIUS
命令还支持使用STORE
或STOREDIST
参数将结果保存至一个有序集合中,二者的区别为STORE
保存的是GeoHash值,而STOREDIST
保存的是指定单位下的距离。
示例
redis> GEOADD buildings 121.5056 31.2335 ShanghaiTower 121.4453 31.2235 JinganTemple
(integer) 2
redis> GEORADIUS buildings 121.4800 31.2300 5 km
1) "ShanghaiTower"
2) "JinganTemple"
# 使用WITHCOORD、WITHDIST以及WITHHASH参数
redis> GEORADIUS buildings 121.4800 31.2300 5 km WITHCOORD WITHDIST WITHHASH
1) 1) "ShanghaiTower"
2) "2.4656" # dist
3) (integer) 4054803507567030 # hash
4) 1) "121.50559991598129272" # coord
2) "31.23349948967888423"
2) 1) "JinganTemple"
2) "3.3788"
3) (integer) 4054756202296433
4) 1) "121.44529849290847778"
2) "31.22350001470528724"
# 指定顺序
redis> GEORADIUS buildings 121.4800 31.2300 5 km DESC
1) "JinganTemple"
2) "ShanghaiTower"
将结果保存至指定有序集合中:
# STORE
redis> GEORADIUS buildings 121.4800 31.2300 5 km STORE zset-1
(integer) 2
redis> ZRANGEBYSCORE zset-1 -inf +inf WITHSCORES
1) "JinganTemple"
2) "4054756202296433"
3) "ShanghaiTower"
4) "4054803507567030"
# STOREDIST
redis> GEORADIUS buildings 121.4800 31.2300 5 km STOREDIST zset-2
(integer) 2
redis> ZRANGEBYSCORE zset-2 -inf +inf WITHSCORES
1) "ShanghaiTower"
2) "2.4656495023008533"
3) "JinganTemple"
4) "3.3787870481515605"
GEORADIUSBYMEMBER
GEORADIUSBYMEMBER
命令与GEORADIUS
命令相似,二者不同之处在于GEORADIUSBYMEMBER
命令以一个存在的元素作为中心,而非指定中心的坐标。
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
对于GEORADIUSBYMEMBER
的参数,可参考GEORADIUS
的介绍。
示例
redis> GEOADD buildings 121.5056 31.2335 ShanghaiTower 121.4453 31.2235 JinganTemple
(integer) 2
redis> GEORADIUSBYMEMBRE buildings ShanghaiTower 10 km
1) "ShanghaiTower"
2) "JinganTemple"
删除Geo类型元素
Geo类型没有类似于其它类型删除元素的GEODEL
命令,但由于Geo类型是基于有序集合实现的,所以可以使用ZREM
命令移除其元素。
redis> GEOADD buildings 121.5056 31.2335 ShanghaiTower
(integer) 1
redis> GEOPOS buildings ShanghaiTower
1) 1) "121.50559991598129272"
2) "31.23349948967888423"
redis> ZREM buildings ShanghaiTower
(integer) 1
# 删除后使用GEOPOS获取不到该元素
redis> GEOPOS buildings ShanghaiTower
(nil)
命令扩展
通过使用Geo类型的相关命令,可以轻松地实现地理位置相关的需求,例如附近热门景点、外卖点餐筛选等。
例如GEORADIUS
命令的示例所示,假定获取到当前的坐标为东经121.4800度,北纬31.2300度,只需要执行GEORADIUS tourist-spots 121.4800 31.2300 5 km WITHDIST WITHCOORD
即可获取到附近5公里内的景区坐标以及距离。