之前用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...