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

2021-08-27 09:12:11 字數 1795 閱讀 4968

接上文,本文將繼續介紹基於solr的地理位置搜尋的第二種實現方案cartesian tiers+geohash

從基於solr的地理位置搜尋(2)中可以看到完全基於geohash的查詢過濾,將完全遍歷整個docment文件,從效率上來看並不太合適,所以結合笛卡爾層後,能有效縮減少過濾範圍,從效能上能很大程度的提高。

構建索引階段:

string geohash = geohashutils.encode(latitude, longitude);

docment.addfield("geohash", geohash);

//cartesian tiers

int tier = start_tier;//開始構建索引的層數

//create a bunch of tiers, each deeper level has more precision

//將一條記錄的經緯度對應全部笛卡爾層的tierboxid作為域值構建索引

for (cartesiantierplotter plotter : plotters)

看到這裡大家肯定明白了。越相近的經緯度在同層肯定會在同乙個網格中,所以他們儲存的

tierboxid就會是一樣。那麼查詢的時候通過經緯度對應層的tierboxid,也就能找到相同層域的docid,但是如果給定的的查詢範圍大,可能需要將若干層的所屬網格的docid都查到。

整個查詢過程是先通過笛卡爾層將若干個網格涉及的doclist存入bitset,如下**所示:

public docidset getdocidset(final indexreader reader) throws ioexception 

}return bits;

}

介紹完笛卡爾層的計算後,接下來介紹笛卡爾層過濾後返還的bitset如何和geohash結合,從實現上講其實很簡單,就是將通過笛卡爾層過濾的資料結果集合 依次遍歷計算其與查詢給定的經緯度座標的球面距離,同時將該計算距離和查詢指定範圍距離進行比較,如果大於給定距離,則將當前記錄繼續過濾掉,那麼最終剩下的資料結果集合,將是滿足查詢條件的地理位置結果集合。具體實現流程見如下**:

//將笛卡爾層的filter作為geohash的filter引數傳遞進去,形成乙個過濾鏈

filter = distancefilter = new geohashdistancefilter(cartesianfilter, lat, lng, miles, geohashfieldprefix);

再看geohashdistancefilter中最核心的方法getdocidset():

public docidset getdocidset(indexreader reader) throws ioexception  else 

//小於給定查詢距離的的docid放入快取,以供下次使用,同時返回true代表當前docid是滿足條件的記錄

if (d < distance) else }};

從上述分析中大家應該可以想到 採用笛卡爾層 filter結合

gohash filter的實現方案,在計算規模上會比單獨使用geohash少了很多,而在查詢效能也會有更優異的表現。

最後附上乙個本地demo的查詢例項:

用geofilter

查詢給定經緯度500km

內的的資料

基於Solr的地理位置搜尋 1

基於solr的空間搜尋學習筆記 在solr中基於空間位址查詢主要圍繞2個概念實現 1 cartesian tiers 笛卡爾層 cartesian tiers是通過將乙個平面地圖的根據設定的層次數,將每層的分解成若干個網格,如下圖所示 每層以2的評方遞增,所以第一層為4個網格,第二層為16 個,所以...

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...