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