Lucene全文搜索學習筆記(三)

個人筆記之用,如有錯誤,懇請批評指正。


高亮,多字段查詢,分頁查詢。

分頁查詢,接上

若查詢第二頁,每頁5條。查詢10條。遍歷取回6-10條。需判斷總條數與需要條數的關係

//總記錄數小於end,說明scoreDocs不滿end條。即返回的是start--totalHits條。否則返回的是start--end條
           ScoreDoc[] scoreDocs = topDocs.scoreDocs;
           int size = end;
           if(topDocs.totalHits<end) {
              size = topDocs.totalHits;
           }


IndexWriterUtil的編寫:整個項目唯一一個IndexWriter,並且在虛擬機關閉時自動close();

//註冊虛擬機關閉線程
       Runtime.getRuntime().addShutdownHook(new Thread(){
 
           @Override
           public void run() {
              try {
                  indexWriter.close();
                  System.out.println("indexWriter已經關閉了!");
              } catch (CorruptIndexException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
           }
       });


做系統不僅要考慮功能,還要考慮非功能的東西,比如說性能,可維護性,交互性等。

IKAnalyzer中文分詞器:開源的,輕量級的分詞器。

使用IKAnalyzer,當參數爲true時,表示使用最大詞長分詞,false表示使用細粒度分詞

步驟:

1、  導包

2、  配置文件IKAnalyzer.cfg.xml到src目錄下

3、  禁用詞彙ext_stopword.dic和自定義詞彙mydict.dic放到src目錄下(/)(格式:第一行空格換行,並注意保存的編碼要一致

禁用詞彙不建立索引庫,所以搜索不到。但是會存儲進索引庫。

4、   //使用IKAnalyzer,當參數爲true時,表示使用最大詞長分詞,false表示使用細粒度分詞

IKAnalyzer = new IKAnalyzer(true);

IndexWriter indexWriter = new IndexWriter(LuceneUtil.getDirectory(), LuceneUtil.getAnalyzer(), LuceneUtil.getMaxFieldLength());

注意:當indexWriter用了IKAnalyzer以後,indexSearcher也要用IKAnalyzer


排序和多字段查詢

//創建排序字段,參數一:指定排序字段;參數二:字段類型;參數三:設置升序或子降序,true爲降序

         SortField goodsId = new SortField("goodsId",SortField.INT,true);

         Sort sort=new Sort();

         //設置排序字段(可以多個字段)到sort對象中,排序的優先級,前者優先於後者

         sort.setSort(goodsId,其它SortField對象);          

         //使用IKQueryParser進行多字段數據查詢

         Query query=IKQueryParser.parseMultiField(new String[]{"goodsName","goodsRemark"},keyword);       

         //執行查詢,使用search(Query query , Filter filter , int n , Sort sort)方法,返回20條記錄,加入排序設置信息

         TopDocs topDocs = indexSearcher.search(query, null,20,sort);//null過濾器

 

排序:

new SortField(“指定排序字段”,“字段類型”,“true:升序 false:降序”);

sort = new sort();

sort.setSort(多個sortField);

多字段:

query = IKQueryParser.parseMultiField(new String[]{“字段名”},“keyword”);

查詢:

indexSearcher.search(query,null,20,sort);

 

//排序+多字段查詢
    public void searchBySortAndMultiField(String keyword){
        try {
            IndexSearcher indexSearcher = IndexSearcherUtil.getIndexSearcher();
            //設置排序
            SortField idField = new SortField("id", SortField.INT, false);
            //SortField contentField = new SortField("content",SortField.STRING,false);
            Sort sort = new Sort();
            sort.setSort(idField);
            //設置多字段查詢
            Query query = IKQueryParser.parseMultiField(new String[]{"title","content"}, keyword);
            TopFieldDocs topFieldDocs = indexSearcher.search(query, null, 20, sort);
            System.out.println("總匹配數:"+topFieldDocs.totalHits);
            ScoreDoc[] scoreDocs = topFieldDocs.scoreDocs;
            for (ScoreDoc scoreDoc : scoreDocs) {
                Document doc = indexSearcher.doc(scoreDoc.doc);
                System.out.println("title:"+doc.get("title")+"content:"+doc.get("content"));
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


高亮:

獲取到Document對象後,對doc中指定字段的指定內容利用HighLighter對象進行高亮返回帶有高亮格式的指定字段值,重新setValuedocument中的對應field中,封裝到對象輸出。

具體步驟:

Document doc = indexSearcher.doc(scoreDocs[i].doc);
//設置高亮格式
Formatter fomatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
//設置需要高亮的關鍵字,指定查詢信息
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(fomatter,scorer);
//制定高亮後的長度,需要SimpleFragmenter類型參數,指定20
int length = 20;
highlighter.setTextFragmenter(new SimpleFragmenter(length));
//設置對哪些字段進行高亮,返回高亮後的結果
String titleResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "title", doc.get("title"));
String contentResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "content", doc.get("content"));


對返回的String判空:

Document doc = indexSearcher.doc(scoreDocs[i].doc);
//設置高亮格式
Formatter fomatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
//設置需要高亮的關鍵字,指定查詢信息
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(fomatter,scorer);
//制定高亮後的長度,需要SimpleFragmenter類型參數,指定20
int length = 20;
highlighter.setTextFragmenter(new SimpleFragmenter(length));
//設置對哪些字段進行高亮,返回高亮後的結果
String titleResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "title", doc.get("title"));
String contentResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "content", doc.get("content"));

 

對HighLighterUtils的抽取

Document doc = indexSearcher.doc(scoreDocs[i].doc);
//設置高亮格式
Formatter fomatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
//設置需要高亮的關鍵字,指定查詢信息
Scorer scorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(fomatter,scorer);
//制定高亮後的長度,需要SimpleFragmenter類型參數,指定20
int length = 20;
highlighter.setTextFragmenter(new SimpleFragmenter(length));
//設置對哪些字段進行高亮,返回高亮後的結果
String titleResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "title", doc.get("title"));
String contentResult = highlighter.getBestFragment(LuceneUtil.getIKAnalyzer(), "content", doc.get("content"));

索引庫優化

indexWriter.optimize()方法使用

新增數據時在提交前使用optimize()方法: 將把產生.cfs的文檔和原來的文檔壓縮併合併爲一個

修改操作類的保存數據方法

indexWriter.optimize();

indexWriter.setMergeFactor()方法使用

關鍵代碼:

//通過設置合併因子合併文件,如下:產生三個cfs文檔(包括合併的)將壓縮合併成一個

indexWriter.setMergeFactor(3);


寫在最後,lucene初步入門,能實現初步的增刪改查,分段、排序、高亮以及索引優化。

增刪改查

Term 對應索引表裏的關鍵詞及字段 newTerm(“字段名”,”字段值”)

TopDocs只包括總記錄數和文檔編號(scoreDoc.doc)

           ScoreDoc[] scoreDocs = topDocs.scoreDocs;
           Document document = indexSearcher.doc(scoreDoc.doc);
通過文檔編號再次查詢searcher.doc(scoreDoc.doc)返回document

update原則:根據字段的值進行修改數據內容,先刪除再添加。如果字段值不存在,則新增一條記錄(文檔),如果字段值唯一,那就相當於根據主鍵修改數據;如果字段值對應多條記錄(文檔),則其他記錄(文檔)將被邏輯刪除後,再添加一條記錄(文檔)。

Delete原則:根據傳入的字段值搜索對應的記錄(文檔),進行刪除。


使用細節:

儘量減少不必要的字段的存儲。Store.YES/Store.NO

不需要檢索的內容儘量不要建立索引。Index.ANALYZED/Index.NOT_ANALYZED/Index.NO

非文本格式需要提前轉化爲字符串。

需要整體存放的內容不要分詞,例如:ID、價格、專業詞。Index.NOT_ANALYZED
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章