隨着移動終端的普及,很多應用都基於LBS功能,附近的某某(餐館、銀行、妹紙等等)。
基礎數據中,一般保存了目標位置的經緯度;利用用戶提供的經緯度,進行對比,從而獲得是否在附近。這里需要在設置出一個字段,是關於編碼的字段,一會看下文哈……
地理位置距離實現目標:
查找附近多少公里內的人或者商家
比如:微信、陌陌、美團、基於O2O的一些APP這些應用或者移動網頁都需要用到地理位置計算
目前來說:移動地理位置距離計算比較好的算法是geohash,特此整理分享。
geohash有以下幾個特點:
第一:geohash用一個字符串表示經度和緯度兩個坐標。
某些情況下無法在兩列上同時應用索引 (例如MySQL 4之前的版本,Google App Engine的數據層等),利用geohash,只需在一列上應用索引即可。
(這里插一句:我們的mysql為字段創建的索引,其實原理就是利用二分法算法來做路徑查詢簡化,快速查找出想要的字段位置)
第二:geohash表示的並不是一個點,而是一個矩形區域。比如編碼wx4g0ec19,它表示的是一個矩形區域。
使用者可以發布地址編碼,既能表明自己位於北海公園附近,又不至於暴露自己的精確坐標,有助於隱私保護。
第三:編碼的前綴可以表示更大的區域。
例如wx4g0ec1,它的前綴wx4g0e表示包含編碼wx4g0ec1在內的更大范圍。 這個特性可以用於附近地點搜索。首先根據用戶當前坐標計算geohash(例如wx4g0ec1)然后取其前綴進行查詢 (SELECT * FROM place WHERE geohash LIKE 'wx4g0e%'),即可查詢附近的所有地點。
Geohash比直接用經緯度的高效很多。
Geohash的最簡單的解釋就是:將一個經緯度信息,轉換成一個可以排序,可以比較的字符串編碼
geohash能做到:
- https://github.com/CloudSide/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多萬行測試數據):
-
索引:


其他資料:
- geohash演示: http://openlocation.org/geohash/geohash-js/
- wiki: http://en.wikipedia.org/wiki/Geohash
- 原理: https://github.com/CloudSide/geohash/wiki
移動端地理算法探討 交流QQ: 187395037
