使用mysql来实现lbs(地理位置服务)功能

现在大型的网站实现的lbs服务基本上是用mongodb的实现定位的(gps不太清楚)。对于小的应用来说,有些大材小用了,而且还大大增加了维护成本。这里用mysql来实现lbs的功能。

以下是从“知乎”网上的一篇文章(http://www.zhihu.com/question/20059072)。

数据库设计层面,有两个方案

(1)字段主要包括 userId,lat,lng。分别代表用户ID、最近一次 Checkin 的经度、纬度。
lat/lng 建立复合索引。

然后通过手机的定位,得到自己的位置,比如记为 myLat,myLng。
代码如下,先做一个计算,算出 1km 所对应的经纬度范围:
double range = 180 / Math.PI * 1 / 6372.797;     //里面的 1 就代表搜索 1km 之内,单位km
double lngR = range / Math.cos(myLat * Math.PI / 180.0);
double maxLat = myLat + range;
double minLat = myLat – range;
double maxLng = myLng + lngR;
double minLng = myLng – lngR;

然后执行 SQL :
SELECT * FROM checkinTable WHERE ((lat BETWEEN ? AND ?) AND (lng BETWEEN ? AND ?))
这四个问号,分别代入变量
minLat、maxLat、minLng、maxLng

然后就可以查询得到结果
但是,这样得到的结果不是有序的。
如果要排序,在客户端执行。
不建议在 SQL 层上执行,因为上述的那个 SQL 是可以用到索引进行查询的,一旦引入排序后,就会影响效率。

(2)高级用法,但是有点大材小用的感觉。
就是使用 Spatial Index(空间索引)。MySQL 5.0 之上的系统,都支持该类型的索引。
数据表可以简化为 userId 和 userLocation。 userLocation 是 Point 类型,同时建立 R-TREE 索引。
SQL 语句直接使用一个非标准的 OpenGIS 函数 DISTANCE 就可以了。
这个部分可以参考 MySQL Spatial Index Manual。如果用其他数据库,应该类似。

经测试发现用这个的方法确实实现。对于小网站来说也足够了。