8、数仓开发
8.1 数据预处理:构建地理位置维表
8.1.1 GeoHash位置编码
GPS坐标位置构建:将相邻坐标点转换成一个相同字符串,方便做相邻地理位置查询匹配。
GeoHash编码:即两个坐标的位置越近,这两个坐标的geohash码的相同的位数越多,只有少数的几位尾数不一样。
基本原理:不断将地球上的经度、纬度范围,进行二分,输出1-0比特,开成一串二进制码(二分的次数越多,输出的二进制串越长)
具体实现参考:https://zhuanlan.zhihu.com/p/35940647
Geohash的0、1串序列是经度0、1序列和纬度0、1序列中的数字交替进行排列的,偶数位对应的序列为经度序列,奇数位对应的序列为纬度序列,在进行第一次划分时,Geohash0、1序列中的前5个bits(11100),那么这5bits中有3bits是表示经度,2bits表示纬度,所以第一次划分时,是将经度划分成8个区段(2^3 = 8),将纬度划分为4个区段(2^2 = 4),这样就形成了32个区域(对应Base32)。如下图
GeoHash将每一个区域画成一块块矩形块,每个矩形块使用一个字符串表示,当我们需要查询附近的点时,通过自己的坐标计算出一个字符串,根据这个字符串定位到我们所在的矩形块,然后返回这个矩形块中的点。例如 wx4e就包含wx4e0e,也就是说wx4e0e在wx4e范围内
目前比较通行的做法就是我们不仅获取当前我们所在的矩形区域,还获取周围8个矩形块中的点。那么怎样定位周围8个点呢?关键就是需要获取周围8个点的经纬度,那我们已经知道自己的经纬度,只需要用自己的经纬度减去最小划分单位的经纬度就行。因为我们知道经纬度的范围,有知道需要划分的次数,所以很容易就能计算出最小划分单位的经纬度。
通过上面这张图,我们就能很容易的计算出周围8个点的经纬度了。有了经纬度就能定位到周围8个矩形块了。这样我们就能获取包括自己所在矩形块的9个矩形块中的所有的点。最后分别计算这些点和自己的距离(由于范围很小,点的数量就也很少,计算量就很少)过滤掉不满足条件的点就行了。
试想一下,我们打开百度地图或者是百度地图,在页面中,我们可以看到一个以自我为中心单位范围的一个圆,之前我一直有疑惑,觉得GeoHash应该是已圆为范围,半径为单位进行搜索附近的标志。那么,在实际开发中,会不会地图上显示的圆,仅仅是一种参考,以表示自己周围范围内的标志,而在代码计算中,依旧是已矩形形式来计算的呢? 这个问题,希望我可以在后面进一步的学习和深入了解相关地图API后得到解答。
附上GeoHash字符串对应地图精度参考图
对了,Redis支持Geo,可查看Redis操作文档API(http://redisdoc.com/geo/geohash.html)
在Redis3.2之后引入的。
具体算法:
常营地铁站(lat:39.9257460000,lng:116.5998310000)
将其按geohash拆分规律拆分后的二进制值应该为
11100 11101 00100 01111 10001 10010 00011 00010 01110 10111 11101
转成10进制得到28 29 4 15 17 18 3