随着信息量的急剧增长,LBS技术现今已与我们的生活密不可分,今天主要分享的是基于MongoDB下,根据经纬度获取附近商家的实现。MongoDB是一个基于分布式文件存储的高性能数据库。
对于距离的计算我们知道两点间直线最短,当两个元素的距离不是很远时,通过区域划分,可以直接使用勾股定理就能算得元素之间的距离。我们平时使用的「附近的人」的功能,元素距离都不是很大,勾股定理算距离足矣。不过需要注意的是,经纬度坐标的密度不一样 (地球是一个椭圆),勾股定律计算平方差时之后再求和时,需要按一定的系数比加权求和,如果不求精确的话,也可以不必加权,当然我们现实生活处于一个三维空间,除了经度和维度之外还有一个高程的概念也就是海拔。
当前主流的距离算法(geoHash算法)包括redis和MongoDB在计算距离是都是使用该算法的,geohash简单来说就是将二位的平面坐标转换成一维的整数,对于地理坐标数据我们不好构建索引,当将其转成一维整数时我们就能够很容易的构建索引提高查询效率,无论是范围的Btree还是精确的hash索引。
首先假设我们将需要索引的整个地图分成16×16的方格,如下图(左下角为坐标0,0 右上角为坐标16,16):
MongoDB在建立索引的时候,会根据相应字段的坐标计算一个可以用来做索引的hash值,这个值叫做geohash,下面我们以地图上坐标为[4,6]的点(图中红叉位置)为例。
我们第一步将整个地图分成等大小的四块,这样我们在实际中 将各个区域的位置定义成对应的编号,00、01、10、11。这样之前的4,6坐标就变成了整数00。
我们可以继续往下细分那么之前的坐标点4,6就变成了0011,当我们继续往下细分的时候得到的结果值就更加精确了,MongoDB中是切了26次5