1. 程式人生 > >Lucene 查詢索引庫

Lucene 查詢索引庫

以後用的分詞庫為IKAnalyzer中文分詞庫。
這裡寫圖片描述

查詢

這裡寫圖片描述

這裡寫圖片描述

說明:這是QueryParser的繼承結構,在這裡我們用的是MultiFieldQueryParser.這個類的好處可以選擇多個屬性進行查詢。而QueryParser只能選擇一個。
這裡寫圖片描述

分頁

先創建出資料:
這裡寫圖片描述

這裡寫圖片描述

讀取資料看看是否建立成功:
這裡寫圖片描述

這裡寫圖片描述
說明:
1) 在全文檢索系統中,一般查詢出來的內容比較多,所以必須將查詢出來的內容進行分頁處理。
2) 原理同hibernate的分頁查詢。在hibernate的分頁查詢中,有兩個引數:
int firstResult 當前頁的第一行在資料庫裡的行數
int maxResult 每頁顯示的頁數

搜尋方式

使用查詢字串

QueryParser->Query物件
可以使用查詢條件
“lucene AND 網際網路” 都出現符合查詢條件
“lucene OR 網際網路” 只要出現其一就符合查詢條件
這裡寫圖片描述

這裡寫圖片描述

自己建立與配置Query物件

關鍵詞查詢(TermQuery)

這裡寫圖片描述

這裡寫圖片描述
注:因為儲存引索的時候是通過分詞器儲存,所以所有的因為在索引
庫裡都為小寫,所以lucene必須得小寫,不然查詢不到。如果使用
查詢字串進行查詢,對應的語法格式為:title:lucene

查詢所有文件

這裡寫圖片描述

如果使用查詢字串,對應語法:*:*

範圍查詢

這裡寫圖片描述
如果使用查詢字串,
第一個: id:[5 TO 15]
第二個: id:{5 TO 15}
注:在lucene中,處理數字是不能直接寫入的,要進行轉化。NumberStringTools幫助類給出了轉化工具:
這裡寫圖片描述

在工具類DocumentUtils中也做相應的轉化:
這裡寫圖片描述

這裡寫圖片描述

萬用字元查詢

這裡寫圖片描述

如果使用查詢字串:title:lucen?

短語查詢

這裡寫圖片描述

上面的0代表第0個位置
上面的1代表第3個位置
使用查詢字串:title:”lucene ? ? 網際網路”

Boolean查詢

可以把多個查詢條件組合成一個查詢條件
這裡寫圖片描述

如圖為:同時滿足title中有lucene關鍵字和ID為5到15的所有索引資料。不包括5和15
使用查詢字串:+id:{5 TO 15} +title:lucene
注意:
1、 單獨使用MUST_NOT 沒有意義
2、 MUST_NOT和MUST_NOT 無意義,檢索無結果
3、單獨使用SHOULD:結果相當於MUST
4、SHOULD和MUST_NOT: 此時SHOULD相當於MUST,結果同MUST和MUST_NOT
5、MUST和SHOULD:此時SHOULD無意義,結果為MUST子句的檢索結果

過濾

這裡寫圖片描述
利用indexSearch.search的過載函式的過濾器引數實現對結果的過濾。從這裡可以看出這是一個範圍過濾器。第二個引數與第三個引數為5,15。但是lucene會把這兩個引數當作字串來對待。所以這樣搜尋結果為0。
進行如下處理:
這裡寫圖片描述
這裡寫圖片描述

凡是數字型別的都必須經過這樣的方式進行處理。

這裡寫圖片描述

凡是日期型別的都必須經過這樣的方式進行處理。這樣才能保證結果的正確性。

排序

相關度得分

實驗一:
在索引庫中內容完全相同的情況下,用幾個關鍵詞搜尋,看是否得分相同。
結果:
同一個關鍵詞得分對於所有的Document是一樣的。但是不同的關鍵詞的分數不一樣。關鍵詞和文字內容匹配越多,得分越高。也就是相關度得分就高
實驗二:
再插入一個Document,在其中的content中增加一個關鍵詞,然後儲存到索引庫中。如圖:
這裡寫圖片描述

在content中,google的後面又加了一個詞”網際網路”。然後再進行搜尋,這個時候,id為26的被排到了第一位。相關度得分最高。因為其他的Document在content中匹配”網際網路”只有一處,而id為26的有兩處。
結果:
同一個關鍵詞如果在所有匹配的文字中的相關度得分不一樣,按照相關度得分從高到低的順序排列。
實驗三:
如果想從百度上排名第一,就得控制相關度得分。在lucene中,可以人為控制相關度得分。如圖:
這裡寫圖片描述
利用Document.setBoost可以控制得分。預設值為1
結論:
利用Document.setBoost可以人為控制相關度得分,從而把某一個引索內容排到最前面。
這裡寫圖片描述

按照某個欄位進行排序

這裡寫圖片描述
如圖所示的程式碼,過載了indexSearcher.search方法。在這個方法中,Sort對 象就是指定的按照id升序排列。SortField.INT指定了ID的型別。型別不一樣,大小的比較就不一樣。
這裡寫圖片描述

上面程式碼查詢出來以後是按照id的升序排列。
這裡寫圖片描述
這個程式碼為按照id的降序排列。其中最後一個引數為reverse
Reverse為false 升序(預設)
Reverse 為true 降序
注:按照某個欄位進行排序與相關度得分沒有關係。

高亮

高亮的作用

1) 使關鍵字的顏色和其他字的顏色不一樣,這樣關鍵字就比較突出。
方法:在關鍵字周圍加上字首和字尾

    <font color=’red’>中國</font>

2) 生成摘要(從關鍵詞出現最多的地方擷取一段文字),可以配置要擷取文字的字元數量。

程式設計步驟

/**
 * 高亮
 *    * 使關鍵字變色
 *       *  設定
 *       *  使用
 *    * 控制摘要的大小
 * @author Administrator
 */
public class HighlighterTest {
    @Test
    public void testSearchIndex() throws Exception{
        IndexSearcher indexSearcher = new IndexSearcher(LuceneUtils.directory);
        QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30, new String[]{"title","content"}, LuceneUtils.analyzer);
        Query query = queryParser.parse("Lucene");
        TopDocs topDocs = indexSearcher.search(query, 25);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        /***********************************************************************/
            /**
             * 給關鍵字加上字首和字尾
             */
            Formatter formatter = new SimpleHTMLFormatter("<font color='red'>","</font>");
            /**
             * scorer封裝了關鍵字
             */
            Scorer scorer = new QueryScorer(query);
            Highlighter highlighter = new Highlighter(formatter,scorer);
            /**
             * 建立一個摘要
             */
            Fragmenter fragmenter = new SimpleFragmenter(10);
            highlighter.setTextFragmenter(fragmenter);
        /***********************************************************************/
        List<Article> articleList = new ArrayList<Article>();
        for(ScoreDoc scoreDoc:scoreDocs){
            float score = scoreDoc.score;
            System.out.println(score);//相關的得分
            Document document =  indexSearcher.doc(scoreDoc.doc);
            Article article = DocumentUtils.document2Article(document);
            /*
             * 使用高亮器
             */
            /**
             * 1、分詞器
             *      查詢關鍵詞
             * 2、欄位
             *      在哪個欄位上進行高亮
             * 3、欄位的內容
             *      把欄位的內容提取出來
             */
            String titleText = highlighter.getBestFragment(LuceneUtils.analyzer, "title", document.get("title"));
            String contentText = highlighter.getBestFragment(LuceneUtils.analyzer, "content", document.get("content"));
            if(titleText!=null){
                article.setTitle(titleText);
            }
            if(contentText!=null){
                article.setContent(contentText);
            }
            articleList.add(article);
        }

        for(Article article:articleList){
            System.out.println(article.getId());
            System.out.println(article.getTitle());
            System.out.println(article.getContent());
        }
    }
}

建立和配置高量器

這裡寫圖片描述

這裡寫圖片描述

一個高亮器的建立需要兩個條件:
Formatter 要把關鍵詞顯示成什麼樣子
Scorer 查詢條件
Fragmenter設定文字的長度。預設為100。
如果文字的內容長度超過所設定的大小,超過的部分將顯示不出來。

使用高亮器

這裡寫圖片描述

這裡寫圖片描述

getBestFragment為得到高亮後的文字。
引數:

  1. 分詞器

    如果是英文:StandardAnalyzer
    如果是中文:IKAnalyzer
    
  2. 在哪個屬性上進行高亮

  3. 要高亮的內容