您的位置:首页 > 其它

开发LBS应用之 根据一点的经纬度实现附近点的查询 - geohash

2015-03-30 17:57 573 查看


开发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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: