附近门店的实现

门店系统作为O2O体系重要的一环,LBS功能自然是当中必不可少的利器。在搭建附近门店的系统,通常情况需要满足这样的需求:

(1)       附近默认距离(比如两公里)内的某商户的门店

(2)       找不到的话,扩大距离继续查询

(3)       查询到门店,返回距离数据

这么看,是球面空间两点的距离分析问题。可是随着门店数据的增加,简单距离计算的次数就会被放大,我们就会自然地考虑到,门店的位置是固定的,能否进行一些预处理,把门店先切片,然后把用户的位置先放到某个片中,再进行距离计算。

第一种思路,经纬度排除。纬度的每个度大约相当于111km,但经度的每个度的距离从0km到111km不等。它的距离随纬度的不同而变化,等于111km乘纬度的余弦。因此,使用纬度天然分隔,是一种解决方案。假设,现在一个用户的经纬度是(22.534756,113.922333),需要查询十公里内的数据,可以采用纬度小数点后一位进行排除,期后再进行经度排除。显然,这种分片方式显得累赘,而且效率和扩展性都不算特别良好。但是它提供了一种思维方式,既然经纬度可以分块,那把这些小块进行编号,再把商家固定在这些编号块上成为预处理数据,用户进入后再采用同样的编码方式把用户固定到小块上,再在同一个小块里面精确计算距离,不是可以解决问题了么?

于是,第二种思路来了,平面切片方式。Geohash就是当中一种采用二分切分的方法,简单介绍一下其实现原理。

1)首先将纬度范围(-90, 90)平分成两个区间(-90, 0)(0, 90) 如果目标纬度位于前一个区间,则编码为0,否则编码为1

2)使用前一个编码为1的区域,继续分割,直到达到精度要求。

3)经度和纬度的编码合并,奇数位是纬度,偶数位是经度。得到一个二进制序列

4)每五位分割序列(base32编码),使用数字0-9以及字母b-z(排除ailo)编码。

5)由于临近两个方格的编码差异极大,因此需要检索的两个点是否在某个范围内,需要进行对周边八个格子的检索。

geohash精度列表

下面的介绍,所使用hash1,即为一位字母编码值,同理,hash6为六位字母编码值。

hash取值

面积(km^2)

大概的纵横(纬度*经度)乘积(km*km

1(地球总面积)

510,065,600

16384*32768

hash1

15,939,500

4096*4096

hash2

498,110

512*1024

hash3

15,565

128*128

hash4

486

32*16

hash5

15

4*4

hash6

0.5

1*0.5

hash7

15625(m^2)

125*125(m*m)

hash8

488.28125(m^2)

31.25*15.625(m*m)

说到这里,假如需要查询附近两公里的门店,应该采用那种hash取值去算呢?

[object Object]

上图为hash6的九宫格排布,图中每个小格都为1KM*0.5KM的面积,用户点在E格中任意位置,于是能看到,九宫格内能保证至少查询出附近0.5KM的门店,要满足2KM的需求,就需要81个格子。同样方式发现hash5只需要九个格子即可满足,但是最大覆盖范围达到了10KM,不满足距离要求门店数量可能会比较多。

分片筛选之后,得到基本满足需要的门店集合,再进行球面距离计算,即可得到门店距离了。

你可能感兴趣的:(附近门店的实现)