lucene數值型別的索引和範圍查詢分析

2021-09-23 20:43:51 字數 2949 閱讀 8590

query q = numericrangequery.newlongrange("idfield", 1l, 10l, true, true);
數值型別建索引的時候,會把數值轉換成多個lexicographic sortable string ,然後索引成 trie 字典樹結構。

例如:假設num1 拆解成 a ,ab,abc ;num2 拆解成 a,ab,abd 。

【圖1】:

通過搜尋ab 可以把帶ab 字首的num1,num2 都找出來。在範圍查詢的時候,查詢範圍內的數值的相同字首可以達到一次查詢返回多個doc 的目的,從而減少查詢次數。

下面講解一下 :數值型別的索引和範圍查詢的工作原理。

1:數值的二進位制表示方式

以long 為例:符號位+63位整數字,符號位0表示正數 1表示負數。

對於正數來說低63位越大這個數越大,對於負數來說也是低63位越大。

如果對符號位取反。則long.min -- long.max 可表示為:0x0000,0000,0000,0000  --  0xffff,ffff,ffff,ffff

經過這樣的轉換後, 是不是從字元層面就已經是從小到大排序了?

2:如何拆分字首

以0x0000,0000,0000,f234為例,每次右移4位。

1:0x0000,0000,0000,f23   與  0x0000,0000,0000,f230 --0x0000,0000,0000,f23f 範圍內的所有數值的字首一是一致的

2:0x0000,0000,0000,f2   與  0x0000,0000,0000,f200 ——0x0000,0000,0000,f2ff 範圍內的所有數值的字首一致

3:0x0000,0000,0000,f  與  0x0000,0000,0000,f000 --0x0000,0000,0000,ffff 範圍內的所有數值的字首一致

0x0如果用右移幾位後的值做key,可以代表乙個相應的範圍。key可以理解成數值的字首

3:對大範圍折成小範圍

lucene 在查詢時候的法做法是對大範圍折成小範圍,然後每個小範圍分別用字首進行查詢,從而減少查詢次數。

4:數值型別的索引的實現

先設定乙個precisionstep (預設4),對數值型別每次右移(n-1)* precisionstep 位。

每次移位後,從左邊開始每7位存入乙個byte,組成乙個byte,

並且在陣列第0位插入乙個特殊byte,標識這次的偏移量。

每個byte可以轉成乙個lexicographic sortable string。

lexicographic sortable string 的字元按字典序排列後,和偏移量,數值的大小順序是一致的。——這個是numericrangequery範圍查詢的關鍵!

long 型別一共64位,如果precisionstep=4,則會有16個lexicographic sortable string。

相當於16個字首對應乙個long數值,再用lucene 的倒序索引,最終索引成類似【圖1】 的那種索引結構。

拆分的關鍵**:

org.apache.lucene.util.numericutils 類的 longtoprefixcodedbytes() 方法

public static void longtoprefixcodedbytes(final long val, final int shift, final bytesrefbuilder bytes) 

}

5:範圍查詢大致思想是從範圍的兩端開始拆分。先把低位的值拆成乙個區間,再移動precisionstep到下乙個高位又並成乙個區間。

最後把小區間裡每個值,按移動的次數,用和索引的同樣方式轉成lexicographic sortable string.進行查詢。

**:org.apache.lucene.util.numericutils 類的 splitrange() 方法

private static void splitrange(

final object builder, final int valsize,

final int precisionstep, long minbound, long maxbound

) {if (precisionstep < 1)

throw new illegalargumentexception("precisionstep must be >=1");

if (minbound > maxbound) return;

for (int shift=0; ; shift += precisionstep) {

// calculate new bounds for inner precision

final long diff = 1l << (shift+precisionstep),

mask = ((1l例如:1001,0001-1111,0010 分步拆分成

1: 1001,0001-1001,1111   ( 第0次偏移後  0x91-0x9f  有15個term )

和 1111,0000 -1111,0010   ( 第0次偏移後 0xf0-0f2  有3個term )

2: 1002,0000 – 1110,1111   右移一次後(0x11- 0x15  有5個term ) 

查詢23個lexicographic sortable string.就可以覆蓋整個區間。

Lucene建立索引和索引的基本檢索

author 百知教育 gaozhy 注 演示 所使用jar包版本為 lucene 5.2.0.jar lucene索引操作建立索引 try catch exception e 索引日期 document.add new field date datetools.datetostring new d...

Lucene的平行索引

有時對於乙個document來說,有一些field會被頻繁地操作,而另一些field則不會。這時可以將頻繁操作的field和其他field分開存放,而在搜尋時同時檢索這兩部分field而提取出乙個完整的document。這要求兩個索引包含的document的數量必須相同。在建立索引的時候,可以同時建...

Lucene索引的建立

lucene索引的建立 1.搜尋引擎之所以檢索速度快其中乙個因素就是對索引的建立。就好像書籍的目錄,可以讓我們迅速定位到內容。這裡引用一張圖說明搜尋過程。從圖中可以很清晰的看到乙個搜尋系統,三個部分 收集資料整理成索引文件,這個過程多是確定你需要檢索的資訊。比如如果你需要檢索圖書館中的書。那麼你可能...