Lucene BooleanQuery相关算法
BooleanQuery對兩種不同查詢場景執(zhí)行不同的算法:
場景1:
所有的子句都必須滿足,而且所有的子句里沒有嵌套BooleanQuery。
例:
a AND b AND c
上面語句表示要同時包含a,b,c三個字符(詞元)的文檔,假如現(xiàn)在索引里包含a的文檔有4,6,8;b的文檔有:2,4,6;c的文檔有:3,4,5,這個語句就是找出編號為4的這個文檔。
注:在倒排索引里存儲的包含某個詞元的文檔列表都是從小到大排列的。
初始狀態(tài)如下:
| a | b | c |
| -> 4 | -> 2 | -> 3 |
| 6 | 4 | 4 |
| 8 | 6 | 5 |
指針表示當(dāng)前遍歷到哪個文檔
第一步:按照每個詞元文檔列表的第一個文檔對詞元排序。排序以后的狀態(tài)如下:
| b | c | a |
| -> 2 | -> 3 | -> 4 |
| 4 | 4 | 6 |
| 6 | 5 | 8 |
第二步:判斷第一個詞元(b)的當(dāng)前遍歷文檔(2)是否小于最后一個詞元(a)的當(dāng)前遍歷文檔(4)。如果小于,則表示第一個詞元的當(dāng)前遍歷文檔不是符合的文檔,如果是符合的最后一個詞元的當(dāng)前文檔應(yīng)該和第一個詞元的相同。
第三步: 第一個詞元文檔位置(2)跳轉(zhuǎn)到最后一個詞元的當(dāng)前遍歷的文檔(4),跳轉(zhuǎn)以后的狀態(tài)如下:
| b | c | a |
| 2 | -> 3 | -> 4 |
| -> 4 | 4 | 6 |
| 6 | 5 | 8 |
第四步: 將第一個詞元放到詞元列表最后,重置位置后狀態(tài)如下:
| c | a | b |
| -> 3 | -> 4 | 2 |
| 4 | 6 | -> 4 |
| 5 | 8 | 6 |
重復(fù)第二、三、四步,直到找到第一個詞元的當(dāng)前遍歷文檔ID和最后一個詞元的相同,則這個文檔就是符合查詢要求的文檔。
這種場景的代碼實(shí)現(xiàn)在ConjunctionScorer類里,主要的代碼邏輯在方法doNext里:
while (more && first().doc() < last().doc()) { // find doc w/ all clauses
more = first().skipTo(last().doc()); // skip first upto last
scorers.addLast(scorers.removeFirst()); // move first to last
}
這里會不斷的判斷第一個詞元的當(dāng)前文檔是否小于最后一個詞元的當(dāng)前文檔,如果不相同,則第一個詞元的文檔跳轉(zhuǎn)到最后一個詞元的文檔位置。
排序是在第一次進(jìn)去的時候在init方法里做的。
場景2:
除了上面第一種場景就是第二種場景,第一種場景因?yàn)榕判虻脑?,不需要遍歷所有的文檔,第二種場景需要遍歷所有的文檔。
第二種場景的實(shí)現(xiàn)在BooleanScorer類里,
每次往BooleanScorer類里添加一個子句,會記錄當(dāng)前這個子句的序號和這個子句的定義,是必須滿足還是必須不滿足。這個數(shù)據(jù)記錄在requiredMask和prohibitedMask中,這兩個數(shù)是int類型,里面每一位都代表一個子句。requiredMask記錄了哪些子句必須滿足;prohibitedMask記錄了哪些子句必須不能滿足。比如一共有5個子句,1、3、5必須滿足,2、4必須不能滿足,則requiredMask二進(jìn)制的值為: 10101。prohibitedMask的值為: 01010。
當(dāng)調(diào)用next的時候會批量從各子句中取出符合這些子句的部分文檔(文檔ID批范圍,1024為一批)到內(nèi)存中的一個緩存BucketTabke里,在這個緩存里會根據(jù)文檔ID進(jìn)行聚合(Bucket),每個文檔ID都有個滿足哪些子句的屬性bits。
然后遍歷這些文檔,那些bits里包含所有必須符合子句且不包含所有必須排查子句的文檔是最終符合的文檔。這個判斷是通過bits和上面requiredMask和prohibitedMask做位運(yùn)算實(shí)現(xiàn)的。
if ((current.bits & prohibitedMask) == 0 &&
(current.bits & requiredMask) == requiredMask) {
return true;
}
總結(jié)
以上是生活随笔為你收集整理的Lucene BooleanQuery相关算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu 14.04开发环境
- 下一篇: Day 03--设计与完善(一)