需求说明

需求来源于条友的一个项目,根据用户当前所在坐标,查询附近企业,并将距离进行倒排,这是个比价常见的需求,现在将实现过程简单描述一下。

 

1、原方案

从数据库中加载所有企业的坐标地址,数据量在万级,每个用户查询一次最近的企业,后台计算量就是数万次,N个用户每查询一次,就是N*数万次。

 

  1. 优化方案

先从数据库中查询出给定范围的企业,这样计算量就小很多,例如只需要查询1公里范围以内的企业,就不需要数万次那么多了。(当然,如果用户选择的是1万公里以内的企业,还是一个全集,所以这个最大范围需要在C端做限制,比如最大只能查询150公里以内的企业)。

 

  1. 方案设计

根据geohash原理,可以理解为将全国地图划分为N个网格,每个网格都有独立的全局12位geohash编码,两个坐标点距离越近,geohash编码的前N位越相似,如图:

 

java判断点是否在矩形内 java判断坐标点所在范围_数据库

Geohash精度说明:

java判断点是否在矩形内 java判断坐标点所在范围_数据_02

根据上图所示,
如果要查询1公里范围内的,就查询前6位

如果要查询5公里范围内的,就查询前5位

如果要查询40公里范围内的,就查询前4位

如果要查询150公里范围内的,就查询前3位

 

  1. 开发步骤

4.1 增加一张企业坐标表

字段名称

类型

长度

备注

 

企业id

同企业表id

同企业表id长度

 

索引

经度

double

小数点后6位

 

 

纬度

double

小数点后6位

 

 

geohashcode

varchar

12

Geohash编码

 

km1

varchar

6

1公里范围

加索引

km5

varchar

5

5公里范围

加索引

km40

varchar

4

40公里范围

加索引

km150

varchar

3

150公里范围

加索引

 

4.2 企业坐标数据录入的时候,同时向该表写入坐标相关数据,前三个字段已经有了,geohashcode字段通过Geohash类计算得到,后面四个字段,分别按对应的长度对geohashcode截取:

km1字段,截取geohashcode的前6位得到

km5字段,截取geohashcode的前5位得到

Km40字段,截取geohashcode的前4位得到

Km150字段,截取geohashcode的前3位得到

 

4.3 用户需要查询企业的时候,如果查询1公里范围内的企业,先将用户坐标转换成geohash编码,再截取用户的geohash编码前6位,拿到这个6位的编码,作为条件去该表查询km1字段值相同的数据,即查询到距离该用户附近1公里的企业列表,拿到该列表再进行之前的排序方案,即可得出距离排序后的企业。