現在幾乎所有的o2o應用中都會存在「按範圍搜素、離我最近、顯示距離」等等基於位置的互動,那這樣的功能是怎麼實現的呢?本文提供的實現方式,適用於所有資料庫。
實現過程主要分為四步:
1. 搜尋
在資料庫中搜尋出接近指定範圍內的商戶,如:搜尋出1公里範圍內的。
2. 過濾
搜尋出來的結果可能會存在超過1公里的,需要再次過濾。如果對精度沒有嚴格要求,可以跳過。
3. 排序
距離由近到遠排序。如果不需要,可以跳過。
4. 分頁
如果需要2、3步,才需要對分頁特殊處理。如果不需要,可以在第1步直接sql分頁。
第1步資料庫完成,後3步應用程式完成。
為了方便下面說明,先給出乙個初始表結構,我使用的是mysql:
搜尋可以用下面兩種方式來實現。
customer表中使用兩個字段儲存了經度和緯度,如果提前計算出經緯度的範圍,然後在這兩個欄位上加上索引,那搜尋效能會很不錯。
那怎麼計算出經緯度的範圍呢?已知條件是移動裝置所在的經緯度,還有滿足業務要求的半徑,這很像初中的一道平面幾何題:給定圓心座標和半徑,求該圓外切正方形四個頂點的座標。而我們面對的是乙個球體,可以使用spatial4j來計算。
geohash的原理不講了,詳細可以看這篇文章,講的很詳細。geohash演算法能把二維的經緯度編碼成一維的字串,它的特點是越相近的經緯度編碼後越相似,所以可以通過字首like的方式去匹配周圍的商戶。
customer表要增加乙個字段,來儲存每個商戶的geohash編碼,並且建立索引。
同樣,排序也需要在應用程式中處理。排序基於上面的過濾結果做就可以了collections.sort(list, comparator)。
如果需要2、3步,只能在記憶體中分頁,做法也很簡單,可以參考這篇文章。
全文的重點都在於搜尋如何實現,更好的利用資料庫的索引,兩種搜尋方式以百萬資料量為分割線,第一種適用於百萬以下,第二種適用於百萬以上,未經過嚴格驗證。可能有人會有疑問,過濾和排序都在應用層做,記憶體占用會不會很嚴重?這是個潛在問題,但大多數情況下不會。看我們大部分的應用場景,都是單一種類poi(point of interest)的搜尋,如酒店、美食、ktv、電影院等等,這種資料密度是很小,1公里內的酒店,能有多少家,50家都算多的,所以最終要看具體業務資料密度。本文沒有分析原理,只講了具體實現,有關分析的文章可以看參考鏈結。
地理距離排序,範圍查詢
參考文章 地理空間距離計算優化 查詢附近的點,即需要對資料庫中的點與當地點的距離排序。1.在乙個球體上,求任意兩點a和b的距離,相當於求乙個弧長,公式為 d 360 2 r r 180 注 周長是弧長的360 倍。只要求出夾角 就能求出弧長,即求出距離。2.然後需要將乙個點的經緯度轉換為r 1的空間...
如何按日期範圍拷貝資料夾
醫院的dicom資料夾,當達到若干t時,ls指令會需要等待很久很久。而dicom資料夾裡的dicom影象又是按序列劃分資料夾的。如何按日期範圍 例如按月 拷貝dicom資料夾回家呢?這裡給出解決方案。這裡按月進行描述,假設要拷貝2019年8月的所有dicom影象。設定你的目標資料夾,例如你的u盤某路...
Mysql select in 按id排序實現方法
表結構如下 mysql select from test id name 1 test1 2 test2 3 test3 4 test4 5 test5 執行以下sql mysql select from test where id in 3,1,5 id name 1 test1 3 test3 ...