赞
踩
GeoHash:GeoHash是一种将二维的经纬度转换成字符串的方法。
原出处:http://www.cnblogs.com/LBSer/p/3310455.html
运用:mongoDB使用geoHash对二维经纬度坐标索引转换为可排序的一维索引,从而可以使用B树类似的二分查找的方式对其进行相关的搜索查询。
如:用户在地图上搜索附近几百米内的饭馆位置。
每一个字符串代表了某一矩形区域。也就是说,这个矩形区域内所有的点(经纬度坐标)都共享相同的GeoHash字符串,同时在大部分情况下,字符串前缀匹配越多的距离越近。
因此,geoHash做了下列几个动作:
1)GeoHash将二维的经纬度转换成字符串。
2)字符串越长,表示的范围越精确。
3)字符串相似的表示距离相近(大部分情况下是的),可以利用字符串的前缀匹配来查询附近的POI信息点。
因此可以使用geoHash执行2维坐标转1维字符串,且转化后的字符串可排序,通过匹配前缀来进行附近搜索。
geoHash的编码方法:逼近编码。
如:北海公园坐标 纬度:39.928167 经度:116.389550
1.对纬度执行类似二分法编码。
2.对经度执行类似的二分法编码,序列:11010 01011。
3.组码。
GeoHash Base32编码长度与精度
详情见下表: 摘自维基百科:http://en.wikipedia.org/wiki/Geohash
为什么分别给经度和维度编码?为什么需要将经纬度两串编码交叉组合成一串编码?
如图所示,我们将二进制编码的结果填写到空间中,当将空间划分为四块时候,编码的顺序分别是左下角00,左上角01,右下脚10,右上角11,也就是类似于Z的曲线,当我们递归的将各个块分解成更小的子块时,编码的顺序是自相似的(分形),每一个子快也形成Z曲线,这种类型的曲线被称为Peano空间填充曲线。
这种类型的空间填充曲线的优点是将二维空间转换成一维曲线(事实上是分形维),对大部分而言,编码相似的距离也相近, 但Peano空间填充曲线最大的缺点就是突变性,有些编码相邻但距离却相差很远,比如0111与1000,编码是相邻的,但距离相差很大。
除Peano空间填充曲线外,还有很多空间填充曲线,如图所示,其中效果公认较好是Hilbert空间填充曲线,相较于Peano曲线而言,Hilbert曲线没有较大的突变。为什么GeoHash不选择Hilbert空间填充曲线呢?可能是Peano曲线思路以及计算上比较简单吧,事实上,Peano曲线就是一种四叉树线性编码方式。
1)由于GeoHash是将区域划分为一个个规则矩形,并对每个矩形进行编码,这样在查询附近POI信息时会导致以下问题,比如红色的点是我们的位置,绿色的两个点分别是附近的两个餐馆,但是在查询的时候会发现距离较远餐馆的GeoHash编码与我们一样(因为在同一个GeoHash区域块上),而较近餐馆的GeoHash编码与我们不一致。这个问题往往产生在边界处。
解决的思路很简单,我们查询时,除了使用定位点的GeoHash编码进行匹配外,还使用周围8个区域的GeoHash编码,这样可以避免这个问题。
2)我们已经知道现有的GeoHash算法使用的是Peano空间填充曲线,这种曲线会产生突变,造成了编码虽然相似但距离可能相差很大的问题,因此在查询附近餐馆时候,首先筛选GeoHash编码相似的POI点,然后进行实际距离计算。
3)geohash只是空间索引的一种方式,特别适合点数据,而对线、面数据采用R树索引更有优势(可参考:深入浅出空间索引:为什么需要空间索引)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。