參考文檔:html
http://blog.csdn.net/wangxiafghj/article/details/9014363geohash 算法原理及實現方式
http://blog.charlee.li/geohash-intro/ geohash:用字符串實現附近地點搜索
http://blog.sina.com.cn/s/blog_7c05385f0101eofb.html 查找附近點--Geohash方案討論
http://www.wubiao.info/372 查找附近的xxx 球面距離以及Geohash方案探討
http://en.wikipedia.org/wiki/Haversine_formula Haversine formula球面距離公式
http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe 球面距離公式代碼實現
http://developer.baidu.com/map/jsdemo.htm#a6_1 球面距離公式驗證
http://www.wubiao.info/470 Mysql or Mongodb LBS快速實現方案算法
如今不少APP都有搜索附近的功能,好比附近的人、附近的店鋪等。要實現這樣的功能,咱們能夠用最笨的方法:根據經緯度計算距離,而後劃定一個閾值,只要小於該閾值就算是附近的。這種方法在數據量小時基本沒問題,可是,若是數據量特別大,那服務器就須要進行大量的計算,負擔很重!爲了解決這一類問題,一個比較經常使用的方法就是利用GeoHash。
1、簡介
GeoHash是一種地址編碼方法。他可以把二維的空間經緯度數據編碼成一個字符串。GeoHash具備如下特色:
一、GeoHash用一個字符串表示經度和緯度兩個座標。在數據庫中能夠實如今一列上應用索引
二、GeoHash表示的並非一個點,而是一個區域;
三、GeoHash編碼的前綴能夠表示更大的區域。例如wx4g0ec1,它的前綴wx4g0e表示包含編碼wx4g0ec1在內的更大範圍。 這個特性能夠用於附近地點搜索
2、計算方法:
GeoHash的計算過程分爲三步:
一、將經緯度轉換成二進制:
好比這樣一個點(39.923201, 116.390705)
緯度的範圍是(-90,90),其中間值爲0。對於緯度39.923201,在區間(0,90)中,所以獲得一個1;(0,90)區間的中間值爲45度,緯度39.923201小於45,所以獲得一個0,依次計算下去,便可獲得緯度的二進制表示,以下表:
最後獲得緯度的二進制表示爲:
10111000110001111001
同理能夠獲得經度116.390705的二進制表示爲:
11010010110001000100
二、合併緯度、經度的二進制:
合併方法是將經度、緯度二進制按照奇偶位合併:
11100 11101 00100 01111 00000 01101 01011 00001
三、按照Base32進行編碼:
Base32編碼表(其中一種):
將上述合併後二進制編碼後結果爲:
wx4g0ec1
3、GeoHash的精度
編碼越長,表示的範圍越小,位置也越精確。所以咱們就能夠經過比較GeoHash匹配的位數來判斷兩個點之間的大概距離。
4、不足之處及解決方法
一、邊緣附近的點,黃色的點要比黑色的點更加靠近紅點,可是因爲黑點跟紅點的GeoHash前綴匹配數目更多,所以獲得黑點更加靠近紅點的結果
解決方法:
能夠經過篩選周圍8個區域內的全部點,而後計算距離獲得知足條件結果。
二、由於現有的GeoHash算法使用的是Peano空間填充曲線(可感興趣的可本身查看),這種曲線會產生突變,形成了編碼雖然類似但距離可能相差很大的問題,所以在查詢附近的時候,首先篩選GeoHash編碼類似的點,而後進行實際距離計算。sql