基於Solr的地理位置搜尋 1

2021-08-27 09:10:03 字數 2056 閱讀 5768

基於solr的空間搜尋學習筆記

在solr中基於空間位址查詢主要圍繞2個概念實現:

(1) cartesian tiers 笛卡爾層

cartesian tiers是通過將乙個平面地圖的根據設定的層次數,將每層的分解成若干個網格,如下圖所示:

每層以2的評方遞增,所以第一層為4個網格,第二層為16 個,所以整個地圖的經緯度將在每層的網格中體現:

笛卡爾層在lucene中對空間地理位置查詢最大的用處在查詢周邊位址的時候有效的減少查詢量,即將查詢量可以控制在分層後最小的網格中的若干docid。

那麼如何構建這樣的索引結構呢,其實很簡單,只需要對應笛卡爾層的層數來構建域即可。

也即是tiers0->field_0,tiers1->field_1,tiers2-field_2,……,tiers19->field_19。(一般20層即可)。每個對應笛卡爾層次的域將根據當前這條記錄的經緯度通過笛卡爾演算法計算出歸屬於當前層的網格,然後將gridid(網格唯一標示)以term的方式存入索引。這樣每條記錄關於笛卡爾0-19的域將都會有乙個gridid對應起來。但是查詢的時候一般是需要查周邊的位址,那麼可能周邊的範圍超過乙個網格的範圍,那麼實際操作過程是根據經緯度和乙個距離確定出需要涉及查詢的從19-0(從高往低查,留給讀者思考)若干層對應的若干網格的資料(關於**實現在後面的文章內容闡述)。那麼乙個經緯度周邊位址的查詢只需要如下圖圓圈內的資料:

所以通過這樣的資料過濾,將極大的減少計算量。

(2) geohash演算法

在lucene索引中將經緯度的二維座標通過geohash,變成乙個一維的字串base32的座標,例如,經緯度對應乙個base32的座標為drt2y,那這個base32的字串什麼意思呢,

其實編碼中每個字元都是代表乙個區域,並且前面的字元是後面字元的父區域,即r是d區域內的子區域,t又為d區域的子區域,大家可以從如下獲得base32的層級關係(以下均來自網際網路):

進入d區域,則看到又分為若干區域,而r為其子區域:

繼續進入r區域,可以繼續看到有子區域t區域:

而2y也是基於以上的關係類推,所以乙個base32的編碼是標示乙個區域,而編碼過程中會根據經緯度的精度來確定這個區域大小。從上面的解釋大家肯定會想到編碼的字首是表示更大的區域。例如wx4g0ec1,它的字首wx4g0e表示包含編碼wx4g0ec1在內的更大區域。所以根據這個特點,利用模糊查詢是可以達到一種附近地點的查詢。

geohash演算法實現其實非常簡單,網上有很多例子,在這裡借用下這些例子再加上比較詳細的說明。基本演算法流程是基於多輪的收斂,以達到滿足精度要求為止。具體流程以(39.92324 緯度, 116.3906 經度)為例,首先將緯度的範圍(-90, 90)平分成兩個區間(-90, 0)、(0, 90),如果目標緯度位在(-90,0),則編碼為0,在(0,90)則編碼為1。由於上面的例子中維度39.92324是屬於(0, 90),所以第一輪獲得的編碼位取1。接下來再將(0, 90)分成 (0, 45), (45, 90)兩個區間,而39.92324位於(0, 45),所以編碼為0。以此類推,直到精度符合要求為止,如下圖所示:

所以通過16輪的計算後得到經度39.92324的編碼為:1011 1000 1100 0111 1001

經度也用同樣的演算法,對(-180, 180)多輪的依次細分計算:

得到經度116.3906的編碼為1101 0010 1100 0100 0100

經緯度的編碼都計算完畢後,接下來就需要合併經緯度的編碼,規則是以經度開始,依次每次取一位合併成5位的新編碼,如上圖紅色字標示順序所示:

完成合併編碼後就需要將該編碼和base32編碼表對應起來,做法是每5位為乙個十進位制數,以11100為例,它的十進位制數是28,所以對應的base32編碼表示w,如下圖所示:

其他的五位編碼依次從表中找到對應位置後,(39.92324 緯度, 116.3906 經度)的base32編碼為:wx4g0ec1

解碼演算法與編碼演算法相反,先進行base32解碼,然後分離出經緯度,最後根據二進位制編碼對經緯度範圍進行細分即可,這裡不再贅述。不過由於geohash表示的是區間,編碼越長越精確,但不可能解碼出完全一致的位址

關於solr+lucene使用cartesian tiers 笛卡爾層和geohash的構建索引和查詢的細節介紹將在新的blog中闡述。

基於Solr的地理位置搜尋(3)

接上文,本文將繼續介紹基於solr的地理位置搜尋的第二種實現方案cartesian tiers geohash 從基於solr的地理位置搜尋 2 中可以看到完全基於geohash的查詢過濾,將完全遍歷整個docment文件,從效率上來看並不太合適,所以結合笛卡爾層後,能有效縮減少過濾範圍,從效能上能...

elasticsearch基於地理位置的搜尋

參考 elasticsearch基於地理位置的搜尋,有乙個專門的物件geo point儲存地理位置資訊 經度,緯度 並且提供了一些基本的查詢方法,如geo bounding box。put my geo name 建立了乙個my geo索引,新增了乙個欄位location,它的型別是geo poin...

基於地理位置資訊的traceroute

我們在機房選擇 測試網路的質量的時候,往往只根據跳數 延遲 抖動 網路吞吐量等指標來衡量,很多時候跳數並不能完全顯示網路拓撲優劣,於是寫了個traceroute結合whois的小腳本來直觀顯示每一跳所處的網路位置。需要安裝mtr和whois 指令碼 root localhost more geotr...