前面为曾经写过一篇博客http://blog.youkuaiyun.com/chenli522/article/details/26697251 根据数据库计算去获取附近的信息。但是随着最近在玩hadoop,在解决Hbase地理位置信息系统的过程中发现,在数据库中进行计算是一种很挫的做法。在数据库中进行计算严重影响速度。
地球数据最简单的形式就是地球上的一个点,由经度和纬度组成。当我们查询数据是我们必须返回同一地点附近的信息。在新的实现方法中,在数据库中,首先需要建立空间索引作为一个字段。使用这个索引作为查询的基础。实现查询的方法有2种,一种是K个最近邻,另外一种是多边形区域内查询。我将分成三章去阐述和实现整个过程。在第一章,我将详细的说明如何建立控件索引。
众所周知,在地球上,标注一个位置信息用的是经纬度,即多数人会建立XY坐标,但是有些甚至建立Z坐标作为海拔高度。再此只以XY来说明一个位置信息。
geohash(地理散列)算法是一种把几个值转换为一个值的算法。下面介绍这个算法 下面以(39.92324, 116.3906)为例,介绍一下geohash的编码算法。首先将纬度范围(-90, 90)平分成两个区间(-90, 0)、(0, 90),如果目标纬度位于前一个区间,则编码为0,否则编码为1。由于39.92324属于(0, 90),所以取编码为1。然后再将(0, 90)分成 (0, 45), (45, 90)两个区间,而39.92324位于(0, 45),所以编码为0。以此类推,直到精度符合要求为止,得到纬度编码为1011 1000 1100 0111 1001。经度也是这样的做法。接下来把纬度和经度编码进行合并,奇数位是纬度,偶数位是经度,最后得到这个位置的编码是11100 11101 00100 01111 00000 01101 01011 00001。最后,用0-9、b-z(去掉a, i, l, o)这32个字母进行base32编码,得到(39.92324, 116.3906)的编码为wx4g0ec1。编码越长说明精确度越高。
常见的一些应用场景
A、如果想查询附近的点?如何操作
查出改点的gehash值,然后到数据库里面进行前缀匹配就可以了。
B、如果想查询附近点,特定范围内,例如一个点周围500米的点,如何搞?
可以查询结果,在结果中进行赛选,将geohash进行解码为经纬度,然后进行比较
*在纬度相等的情况下:
*经度每隔0.00001度,距离相差约1米;
*每隔0.0001度,距离相差约10米;
*每隔0.001度,距离相差约100米;
*每隔0.01度,距离相差约1000米;
*每隔0.1度,距离相差约10000米。
*在经度相等的情况下:
*纬度每隔0.00001度,距离相差约1.1米;
*每隔0.0001度,距离相差约11米;
*每隔0.001度,距离相差约111米;
*每隔0.01度,距离相差约1113米;
*每隔0.1度,距离相差约11132米。
最后要去查询附近的信息,只要编码相似的越多那么说明距离越近。下一章将详细的介绍用K个最近邻去实现查询的方法