redis之十三(查询附近的人——GEO)

受过高等教育的我们都知道,我们所处的任何位置都可以用经度和纬度来标识,经度的范围 -180 到 180,纬度的范围为 -90 到 90。纬度以赤道为界,赤道以南为负数,赤道以北为正数;经度以本初子午线(英国格林尼治天文台)为界,东边为正数,西边为负数。

Redis 在 3.2 版本中增加了 GEO 类型用于存储和查询地理位置,关于 GEO 的命令不多,主要包含以下 6 个:

  1. geoadd:添加地理位置
  2. geopos:查询位置信息
  3. geodist:距离统计
  4. georadius:查询某位置内的其他成员信息
  5. geohash:查询位置的哈希值
  6. zrem:删除地理位置

下面我们分别来看这些命令的使用。

基础使用

添加地理位置

我们先用百度地图提供的经纬度查询工具,地址:

拾取坐标系统

如下图所示:

百度经纬度查询工具.png

找了以下 4 个地点,添加到 Redis 中:

  1. 天安门:116.404269,39.913164
  2. 月坛公园:116.36,39.922461
  3. 北京欢乐谷:116.499705,39.874635
  4. 香山公园:116.193275,39.996348

代码如下:

127.0.0.1:6379> geoadd site 116.404269 39.913164 tianan
(integer) 1
127.0.0.1:6379> geoadd site 116.36 39.922461 yuetan
(integer) 1
127.0.0.1:6379> geoadd site 116.499705 39.874635 huanle
(integer) 1
127.0.0.1:6379> geoadd site 116.193275 39.996348 xiangshan
(integer) 1

相关语法:

geoadd key longitude latitude member [longitude latitude member ...]

重点参数说明如下:

  • longitude 表示经度
  • latitude 表示纬度
  • member 是为此经纬度起的名字

此命令支持一次添加一个或多个位置信息。

查询位置信息

127.0.0.1:6379> geopos site tianan
1) 1) "116.40541702508926392"
   2) "39.91316289865137179"

相关语法:

geopos key member [member ...]

此命令支持查看一个或多个位置信息。

距离统计

127.0.0.1:6379> geodist site tianan yuetan km
"3.9153"

可以看出天安门距离月坛公园的直线距离大概是 3.9 km,我们打开地图使用工具测试一下咱们的统计结果是否准确,如下图所示:

天安门到月坛公园距离统计图.png

可以看出 Redis 的统计和使用地图工具统计的距离是完全吻合的。

注意:此命令统计的距离为两个位置的直线距离。

相关语法:

geodist key member1 member2 [unit]

unit 参数表示统计单位,它可以设置以下值:

  • m:以米为单位,默认单位;
  • km:以千米为单位;
  • mi:以英里为单位;
  • ft:以英尺为单位。

查询某位置内的其他成员信息

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km
1) "tianan"
2) "yuetan"

此命令的意思是查询天安门(116.405419,39.913164)附近 5 公里范围内的成员列表。

相关语法:

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

可选参数说明如下。

1. WITHCOORD

说明:返回满足条件位置的经纬度信息。

示例代码:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km withcoord
1) 1) "tianan"
   2) 1) "116.40426903963088989"
      2) "39.91316289865137179"
2) 1) "yuetan"
   2) 1) "116.36000186204910278"
      2) "39.92246025586381819"

2. WITHDIST

说明:返回满足条件位置与查询位置的直线距离。

示例代码:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km withdist
1) 1) "tianan"
   2) "0.0981"
2) 1) "yuetan"
   2) "4.0100"

3. WITHHASH

说明:返回满足条件位置的哈希信息。

示例代码:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km withhash
1) 1) "tianan"
   2) (integer) 4069885552230465
2) 1) "yuetan"
   2) (integer) 4069879797297521

4. COUNT count

说明:指定返回满足条件位置的个数。

例如,指定返回一条满足条件的信息,代码如下:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km count 1
1) "tianan"

5. ASC|DESC

说明:从近到远|从远到近排序返回。

示例代码:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km desc
1) "yuetan"
2) "tianan"
127.0.0.1:6379> georadius site 116.405419 39.913164 5 km asc
1) "tianan"
2) "yuetan"

当然以上这些可选参数也可以一起使用,例如以下代码:

127.0.0.1:6379> georadius site 116.405419 39.913164 5 km withdist desc
1) 1) "yuetan"
   2) "4.0100"
2) 1) "tianan"
   2) "0.0981"

5. 查询哈希值

127.0.0.1:6379> geohash site tianan
1) "wx4g0cgp000"

相关语法:

geohash key member [member ...]

此命令支持查询一个或多个地址的哈希值。

6. 删除地理位置

127.0.0.1:6379> zrem site xiaoming
(integer) 1

相关语法:

zrem key member [member ...]

此命令支持删除一个或多个位置信息。

代码实战

from redis import StrictRedis

resid_cli = StrictRedis(host="", port=xx, password="xx", db=xx, decode_responses=True)

# geoadd:添加地理位置(可以添加多个,模型是zset)
"""
参数一:key值
参数二,参数三:经度,纬度
参数四:为前面经度 ,纬度代表的点起的名称
"""
resid_cli.geoadd("beijing", 116.403963, 39.915119, "tiananmen", 116.403414, 39.924091, "gugong", 116.419342, 39.888663, "tiantan")
tian = resid_cli.zrange("beijing", 0, -1)
print(tian)

# geopos:查询位置信息
"""
参数一:key值
参数二,三,。。。:存入时经度,纬度的名称
"""
pos = resid_cli.geopos("beijing", "tiananmen", "gugong", "tiantan")
print(pos)

# geodist:距离统计(单位默认为米)
"""
参数一:key值
参数二,参数三:两个位置名称
参数四:距离单位(默认为m)
"""
juli = resid_cli.geodist("beijing", "tiananmen", "gugong", "km")
print(juli)

# georadius:查询距离某个位置指定直径范围内的点
"""
参数一:key值
参数二,参数三:经度,纬度
参数四:距离值
参数五:单位
"""
other = resid_cli.georadius("beijing", 116.403963, 39.915119, 1, "m")
print(other)

# geohash:查询位置的哈希值
"""
参数一:key值
参数二,三,。。。:具体位置的名称
"""
pos_hash = resid_cli.geohash("beijing", "tiananmen", "gugong")
print(pos_hash)

# zrem:删除地理位置
"""
参数一:key值
参数二,三,。。。:具体位置的名称
"""
resid_cli.zrem("beijing", "tiananmen", "tiantan")
tian = resid_cli.zrange("beijing", 0, -1)
print(tian)

应用场景

Redis 中的 GEO 经典使用场景如下:

  1. 查询附近的人、附近的地点等;
  2. 计算相关的距离信息。

小结

GEO 是 Redis 3.2 版本中新增的功能,只有升级到 3.2+ 才能使用,GEO 本质上是基于 ZSet 实现的,这点在 Redis 源码找到相关信息,我们可以 GEO 使用实现查找附近的人或者附近的地点,还可以用它来计算两个位置相隔的直线距离。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值