使用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。如果用其他数据库,应该类似。
经测试发现用这个的方法确实实现。对于小网站来说也足够了。