开发LBS应用之 根据一点的经纬度实现附近点的查询 - geohash
开发LBS应用之 根据一点的经纬度实现附近点的查询 - geohash
时间 2014-07-31 15:13:13 segmentfault-博客 原文 http://blog.segmentfault.com/cloudmario/1190000000624088
geohash
这年头和LBS相关的应用越来越火. 从最早的foursquare的热闹程度就可见一般, 现在就更不用说微信、陌陌了 (什么, 没听过… 哥们, 你out 了). 和LBS有关的应用一般都包括一些共同的操作, 最常见的一个, 就是找附近的东东(餐馆, 商店, 妞….). 所以, 这里就抛出了一个问题, 怎样才能在大量经纬度数据中检索出附近的点呢?
geohash能做到:
- https://github.com/CloudSide/geohash
- https://github.com/lyokato/objc-geohash
例如: 假设我的数据库里存储着1亿条包含经纬度的用户数据,用iPhone/android手机定位得到 新浪总部(理想国际大厦)的经纬度: 39.98123848, 116.30683690 然后去数据库查找附近的妞
require_once(‘geohash.class.php’); $geohash = new Geohash; //得到这点的hash值 $hash = $geohash->encode(39.98123848, 116.30683690); //取前缀,前缀约长范围越小 $prefix = substr($hash, 0, 6); //取出相邻八个区域 $neighbors = $geohash->neighbors($prefix); array_push($neighbors, $prefix); print_r($neighbors);
得到9个geohash值
//得到9个geohash值 Array ( [top] => wx4eqx [bottom] => wx4eqt [right] => wx4eqy [left] => wx4eqq [topleft] => wx4eqr [topright] => wx4eqz [bottomright] => wx4eqv [bottomleft] => wx4eqm [0] => wx4eqw )
范围如图:
用sql语句查询
SELECT FROM xy WHERE geohash LIKE ‘wx4eqw%’; SELECT FROM xy WHERE geohash LIKE ‘wx4eqx%’; SELECT FROM xy WHERE geohash LIKE ‘wx4eqt%’; SELECT FROM xy WHERE geohash LIKE ‘wx4eqy%’; SELECT FROM xy WHERE geohash LIKE ‘wx4eqq%’; SELECT FROM xy WHERE geohash LIKE ‘wx4eqr%’; SELECT FROM xy WHERE geohash LIKE ‘wx4eqz%’; SELECT FROM xy WHERE geohash LIKE ‘wx4eqv%’; SELECT * FROM xy WHERE geohash LIKE ‘wx4eqm%’;
看一下是否用上索引 (一共有50多万行测试数据):
索引:
数据:
看一下查询是否够高效?:
EXPLAIN SELECT * FROM xy WHERE geohash LIKE ‘wx4eqw%’;
恩, HOHO!!
其他资料:
- geohash演示: http://openlocation.org/geohash/geohash-js/
- wiki: http://en.wikipedia.org/wiki/Geohash
- 原理: https://github.com/CloudSide/geohash/wiki
还没有评论,来说两句吧...