Lucene 如何通過GeoHash 查詢距離

2022-02-24 06:11:11 字數 1968 閱讀 6218

之前用lucene做過位置距離查詢的專案,其中lucene搜尋定位距離的原理就是geohash,關於geohash的介紹看這裡geohash 介紹,這篇文章要說的是如何根據geohash查詢距離。

以下面以這幅圖來看,將經度為0作為x軸的原點,緯度為0作為y軸的原點,圖中為了問題簡單化,僅化了3層,實際中3層是不夠的。

假設座標軸正方向表示1,負方向表示0。那麼按照geohash方法劃分區域,則a到j的geohash分別為:

位置點geohash經度值

geohash緯度值

geohash值(經度+維度)

a1 0 0

1 0 0

11 00 00

b1 0 0

0 1 1

10 01 01

c0 1 1

0 1 1

00 11 11

d0 1 1

1 0 0

01 10 10

e1 1 0

1 1 0

11 11 00

f1 1 1

1 1 1

11 11 11

g1 1 1

1 1 1

11 11 11

h1 1 1

0 1 1

01 11 11

i0 1 0

0 1 0

00 11 00

j0 0 0

1 1 1

01 01 01

情況1:

我們看e、f兩個點,其中前兩層都是11,僅第三層不一致,e、f離得很近。

情況2:

我們看e、i兩個點,第

二、三層匹配,僅第一層不一致,e、i卻離得很遠。同理b、j也一樣。

推測結果:

那麼我們可以這樣認為,geohash匹配距離時,必須從前往後,直到第乙個不能匹配為止,匹配的層數越多越相近。

情況3:

拿著結果1,我們看f、g兩個點,三層完全匹配,是不是f、g的距離要比e、f的距離近呢?不是,e、f距離更近。

情況4:

加速a、b、c、d無限靠近原點,那麼a、b、c、d應該離得非常近,但是我們看geohash,a、b、c、d並不是按照從前往後匹配的。

分析結果

geohash並不是通過從前往後匹配來判斷距離的,推測結果是錯誤的,那是通過什麼呢?下面是我的猜測,具體實現思路還需要看看lucene的原始碼。

a、b、c、d四個點,如果按字串從前往後匹配,那麼匹配程度非常低,但是如果把hash當成乙個二進位制數,100表示4,而011表示3,通過數的差的絕對值,我們發現,無論是經度還是維度,a、b、c、d之間的差的絕對值都不會大於一。因為a、b、c、d無限靠近原點,即使有geo劃分有無限層,a的維度是1 0 0 0 0 0...(無限0),b的維度是0 1 1 1 1 1...(無限1),那麼他們的絕對值仍然不會大於1。同樣的,abcd任意兩點的經緯度差絕對值不會大於1。由於都是整數,除了0之外,最小差絕對值就是1。

由此我們可以推論:判斷兩個點的距離,是通過geohash的經緯度hash分別按照二進位製取差,絕對值越小,則距離越近。

至於經度和維度的合併的距離,由於經緯度是完全垂直的,就可以根據平方和(勾股定理)來定了。

如何判斷f、g要比e、f遠,應該就沒有辦法,因為這兒劃分的層次太少,當劃分層次多的時候,經緯度絕對值差e、f自然會比f、g小。所以,分層的大小直接影響到距離的精度。

以上都是自己分析的,不知是否正確,如有錯誤,歡迎批評指正。

Lucene 如何編寫Lucene程式

lucene版本 7.1 使用lucene的關鍵點 建立文件 document 新增檔案 field 儲存了原始資料資訊 把文件加入indexwriter 使用queryparser.parse 構建查詢內容 使用indexsearcher的search 方法,進行查詢 一 建立索引基本流程 ope...

如何建立Lucene索引

需要用到的ipa indexwriter 這個是索引建立的中心元件,通過他就可以建立索引,它是生成索引的過程 與讀取和搜尋索引沒有關係 初始化化它時,需要傳遞的兩個引數。第乙個是引數是指定索引建立的位置,第二是引數是配置分詞器。document 這個文字相當於資料庫中的一條記錄,它裡面需要新增fie...

通過佇列解決Lucene檔案併發建立索引

public sealed class searchindexmanager public static searchindexmanager getinstance queue queue new queue 向佇列中新增資料 public void addqueue string id,stri...