Redis地理算法GEO解析和应用

背景

  1. 获取周边信息;附近人?附近的公司?附近的餐厅?附近的星巴克?
  2. 获取两个坐标位置的距离?

实现

可以使用redis、mongo、mysql进行坐标检索换算实现,redis适用版本: >= 3.2.0

GEO算法

wiki:https://en.wikipedia.org/wiki/Geohash

redis使用通用的GeoHash算法进行处理,首先假设有上海站坐标(121.455708,31.249574),然后根据二分法(左标记0;右标识1)

  • 纬度[-90,90],分为[-90,0),[0,90],称为左右区间,可以确定31.249574属于右区间[0,90],给标记为1;
  • 再将右区间[0,90],分为[0,45),[45,90]左右区间,可以确定31.249574属于左区间[0,90],给标记为0;
  • 依次类推最终可以无限接近具体坐标31.249574经度同理
  • 假设给出最后:纬度的pv为:10101 10001,经度的pv为:11010 11001,pv的长度与给定的区间划分次数有关。
  • 偶数放经度,奇数放纬度重新排列组合最后结果为:11011 00110 11010 00011
  • 将重新排列后的结果转化为十进制后分别为:27、6、2、3,然后使用0-9、b-z(去掉a, i, l, o)这32个字母进行base32编码 结果为:v6u3 (注:参考下方参照码)
  • 在 Redis 中,经纬度使用 52 位的整数进行编码,然后存放至 zset 里面,zset 的 value 是元素的 key,score 是 GeoHash 的 52 位整数值。zset 的 score 虽然是浮点数,但是对于 52 位的整数值,可以做到无损存储。

经度pv划分计算:

pv min mid max
1 -90 0 90
0 0 45 90
1 0.000  22.5 45
0 22.5 33.75 45
1 22.5 28.125 33.75
1 28.125 30.9375 33.75
0 30.9375 32.34375 33.75
0 30.9375 31.640625 32.34375
0 30.9375 31.2890625 31.640625
1 30.9375 31.11328125 31.2890625

纬度pv划分计算:

pv min mid max
1 -180 0 180
1 0 90 180
0 90 135 180
1 90 112.5 135
0 112.5 123.75 135
1 112.5 118.125 123.75
1 118.125 120.9375 123.75
0 120.9375 122.34375 123.75
0 120.9375 121.640625 122.34375
1 120.9375 121.2890625 121.640625

Base32位编码参照

Redis Shell命令

注:时间复杂度: 每添加一个元素的复杂度为 O(log(N)) , 其中 N 为键里面包含的位置元素数量。

扫描二维码关注公众号,回复: 11964912 查看本文章

1、GEOADD -----添加坐标命令(先经度, 后纬度

GEOADD key longitude latitude member [longitude latitude member …]

eg: 

192.168.0.102:4>geoadd coordinate 121.455708 31.249574 "上海站" 121.475164 31.228816 "上海人民广场"
"2"
192.168.0.102:4>geoadd coordinate 121.499717 31.239702 "东方明珠塔"
"1"

2、GEOPOS -----查询坐标信息

GEOPOS key member [member …]

eg:

192.168.0.102:4>geopos coordinate "东方明珠塔"
 1)    1)   "121.49971514940261841"
  2)   "31.23970195235578018"

192.168.0.102:4>geopos coordinate "东方明珠塔" "上海站"
 1)    1)   "121.49971514940261841"
  2)   "31.23970195235578018"

 2)    1)   "121.45570546388626099"
  2)   "31.24957469127141252"

3、GEODIST ----- 查询给定位置之间的距离

注:指定单位的参数 unit 必须是以下单位的其中一个,默认为m:

  • m 表示单位为米(默认)。

  • km 表示单位为千米。

  • mi 表示单位为英里。

  • ft 表示单位为英尺。

GEODIST key member1 member2 [unit]

eg:

192.168.0.102:4>geodist coordinate "上海站" "东方明珠塔"
"4326.7279"
192.168.0.102:4>geodist coordinate "上海站" "东方明珠塔" km
"4.3267"

4、GEORADIUS ----- 查询周围信息

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

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

eg:

192.168.0.102:4>georadius coordinate 121.458175 31.242564 3 km WITHDIST asc count 5
 1)    1)   "上海站"
  2)   "0.8144"

 2)    1)   "上海人民广场"
  2)   "2.2245"

192.168.0.102:4>georadius coordinate 121.458175 31.242564 5 km WITHDIST asc count 5
 1)    1)   "上海站"
  2)   "0.8144"

 2)    1)   "上海人民广场"
  2)   "2.2245"

 3)    1)   "东方明珠塔"
  2)   "3.9632"

192.168.0.102:4>

5、GEORADIUSBYMEMBER  ----- 查询周围信息

注:和GEORADIUS 类似只是将坐标换位具体元素

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

eg:

192.168.0.102:4>georadiusbymember coordinate "上海站" 5 km WITHDIST asc count 5
 1)    1)   "上海站"
  2)   "0.0000"

 2)    1)   "上海人民广场"
  2)   "2.9589"

 3)    1)   "东方明珠塔"
  2)   "4.3267"

6、GEOHASH ----- 查询hash值

注:一般只用于开发调试

GEOHASH key member [member …]

eg:

192.168.0.102:4>geohash coordinate "上海站"
 1)  "wtw3gbc3gn0"

是不是很Easy? ^_^

 

猜你喜欢

转载自blog.csdn.net/qq_31150503/article/details/107380100
今日推荐