Apache Lucene(全文檢索引擎)—搜索

目錄

  返回目錄:http://www.cnblogs.com/hanyinglong/p/5464604.htmlhtml

  本項目Demo已上傳GitHub,歡迎你們fork下載學習:https://github.com/kencery/Lucene_Compass(項目內部有很詳細的註釋)git

1. 搜索思路

  a. 當用戶在搜索的時候,先在詞彙表中查找,獲得符合條件的文檔編號列表,再根據文檔編號去索引庫中獲得數據(Document)。github

  b. Lucene實現搜索的思路apache

    b.1 首先把須要查詢的字符串轉換爲Query對象,把查詢字符串轉換爲Query須要使用QueryParser、MultiFieldQueryParser,查詢字符串首先也要通過分詞器(Analyzer),要求搜索時使用的Analyzer和創建索引的時候使用的Analyzer要一致,不然極有可能搜索不出正確的結果。數組

    b.2 調用indexSearcher.search()進行查詢獲得結果,此方法返回值爲TopDocs,是包含結果的多個信息的一個對象,其中有totalHits表明總記錄數,ScoreDoc數組表明一個結果的相關度得分和文檔編號等信息的對象。框架

    b.3 取出須要的數據文檔編號列表,調用Document doc=indexSearcher.doc(docId)以取出指定編號對應的Document數據。函數

2. 理解核心搜索類

  a.  public class org.apache.lucene.search.IndexSearcher性能

    a.1 IndexSearch是用來在創建好的索引上進行搜索的,它提供了不少搜索方法,其中一些在抽象基類Searcher中實現學習

    a.2 它只能以只讀的方式打開一個索引,因此能夠有多個IndexSearcher的實例在一個索引上進行操做。測試

    a.3 在使用完IndexSearcher後,須要釋放資源,調用方法:indexSearcher.getIndexReader().close();

  b. public final class org.apache.lucene.index.Term

    b.1 Term是搜索的基本單元,一個Term對象由兩個Sting類型的域組成,字段的名稱和字段的值

    b.2  在搜索時,你能夠建立Term對象並和TermQuery同時使用,其中第一個參數表明了要在文檔的哪個Field上進行查找,第二個參數表明了要查詢的關鍵字

      Query query=new TermQuery(new Term("content","lucene"));

      TopDocs topDocs= indexSearcher.search(query,100 );  //返回查詢出來的前n條結果

    b.3 這段代碼使用Lucene查找出content字段中含有單詞lucene的全部文檔,由於TermQuery對象繼承自它的抽象父類Query,因此你能夠在等式的左邊用Query類型。

  c.  public abstract class org.apache.lucene.search.Query

    c.1 Query是一個抽象類,這個類的目的是把用戶輸入的查詢字符串封裝成Lucene可以識別的Query。

    c.2 Query包含了不少子(必須經過一系列子類來表達檢索的具體需求,在4個模塊中有說明),具體請同時按住Ctrl+T查看

  d. public class org.apache.lucene.search.TermQuery 

    d.1 TermQuery是抽象類Query的一個子類,他同時也是Lucene支持的最爲基本的一個查詢類。

    d.2 生成一個TermQuery對象由以下語句完成(它的構造函數主要只接受一個參數,那就是一個Term對象)。

      TermQuery query=new TermQuery(new Term("content","lucene"));

  e. public class org.apache.lucene.search.TopDocs 

    e.1 TopDocs是用來保存搜索的結果的,思路是:指向相互匹配的搜索條件的前N個搜索結果,它是指針的簡單容器指向他們的搜索結果輸出的文檔。

    e.2 基於性能的考慮,TopDocs的實例並非從索引中加載全部匹配查詢的全部文檔,而是每次按照你給的條件查詢出一小部分展示給用戶(分頁原理)。

  f.QueryParser和MultiFieldQueryParser

    f.1 QueryParser查詢分析器,處理用戶輸入的查詢條件,把用戶輸入的非格式話檢索詞轉化成後臺可使用的Query對象。

    f.2 MultiFieldQueryParser是QueryParser的子類,與父類相比,MultiFieldQueryParser能夠在多個屬性中搜索。

3. 關鍵字搜索的大體實現

  a. 代碼以在github上開源,地址:https://github.com/kencery/Lucene_Compass

 1     /**
 2      * 測試搜索
 3      * @throws Exception
 4      */
 5     @Test
 6     public void testSearch() throws Exception {
 7         //1 搜索條件
 8         String queryCondition="lucene";
 9         //2 執行搜索(lucene)
10         List<Article> articles=new ArrayList<Article>();
11         //--------------------------搜索代碼-----------------------------
12         Directory directory=FSDirectory.open(Paths.get("./indexDir/"));  //索引庫目錄
13         Analyzer analyzer=new StandardAnalyzer();        //分詞器
14 
15         //2.1 把查詢字符串轉爲Query對象(只在title中查詢)
16         QueryParser queryParser=new QueryParser("title",analyzer);
17         Query query=queryParser.parse(queryCondition);
18 
19         //2.2 執行搜索獲得結果
20         IndexReader indexReader=DirectoryReader.open(directory);
21         IndexSearcher indexSearcher=new IndexSearcher(indexReader);
22         TopDocs topDocs= indexSearcher.search(query, 100); //返回查詢出來的前n條結果
23 
24         Integer count= topDocs.totalHits; //總結果數量
25         ScoreDoc[] scoreDocs=topDocs.scoreDocs;  //返回前N條結果信息
26 
27         //2.3 處理結果
28         for (int i = 0; i < scoreDocs.length; i++) {
29             ScoreDoc scoreDoc=scoreDocs[i];
30             int docId=scoreDoc.doc;
31             System.out.println("得分是:"+scoreDoc.score+",內部編號是:"+docId);
32             //根據內部編號取出真正的Document數據
33             Document doc=indexSearcher.doc(docId);
34             //將document轉化爲Article
35             Article article=new Article(Integer.parseInt(doc.get("id")), doc.get("title"), doc.get("content"));
36             articles.add(article);            
37         }
38         //------------------------------------------------------------
39         //3  控制檯顯示結果
40         System.err.println("總結果數:"+count);
41         for (Article article : articles) {
42             System.out.println("查詢結果爲:"+article);
43         }
44         indexSearcher.getIndexReader().close();
45     }

4.內建Query對象闡述

  a. BooleanQuery 布爾搜索,對應的查詢語句:

    a.1 BooleanQuery是實際開發過程當中常用的一種查詢,它其實就是一個組合的Query,在使用中的時候能夠把各類Query對象添加進去而且標明它們之間的邏輯關係。

    a.2 BooleanQuery是能夠嵌套的(BooleanQuery是一個布爾子句的容器)

      (1) 一個BooleanQuery能夠成爲另外一個BooleanQuery的條件子句。

      (2) 布爾型的子句數目不能跟你超過1024。

    a.3 public void add(Query query,BooleanClause.Occur occur),BooleanClause表示布爾查詢子句關係的類,包括:BooleanClause.Occur.MUST、BooleanClause.Occur.MUST_NOT、BooleanClause.Occur.SHOULD,它含有如下6種組合。

      (1) MUST和MUST:取得兩個查詢子句的交集。

      (2) MUST和MUST_NOT:表示查詢結果中不能包含MUST_NOT所對應的查詢子句的檢索結果

      (3) MUST_NOT和MUST_NOT:無心義,檢索無結果

      (4) SHOULD和MUST:無心義,結果爲MUST子句的檢索結果

      (5) SHOULD和MUST_NOT:SHOULD功能同MUST,至關於MUST和MUST_NOT的檢索結果

      (6) SHOULD和SHOULD:表示"或"的關係,最終檢索結果爲全部檢索子句的並集。

        Query query1=new MatchAllDocsQuery(); 

        Query query2=NumericRangeQuery.newIntRange("id", 5, 15, true, false);

        booleanQuery.add(query1,Occur.MUST);

        booleanQuery.add(query2,Occur.MUST_NOT);

          對應的查詢字符串爲:+*:* -id:[5 TO 15}

  b. NumericRangeQuery 範圍搜索

    b.1 NumericRangeQuery.newIntRange(String field,Integer min,Integer max,boolean minInclusive,boolean maxInclusive);  布爾型的後面的兩個參數表示是否能夠將兩個臨界值也加入到搜索中。

      例如:Query query=NumericRangeQuery.newIntRange("id", 5, 15, true, false);

        對應的查詢語句:對應的查詢字符串爲:id:[5 TO 15}

  c. PrefixQuery 前綴查詢,查詢出某個字段以什麼開頭的信息

    Term term=    new Term("content","這是");

    PrefixQuery query=new PrefixQuery(term); 

      對應的查詢語句:content:這是*

  d. PhraseQuery短語查詢

    d.1 PhraseQuery提供了一種爲"坡度"的參數,用於表示詞組的兩個字之間能夠插入無關單詞的個數

      PhraseQuery phraseQuery=new PhraseQuery();

      phraseQuery.add(new Term("title","lucene")); 

      phraseQuery.add(new Term("title","框架"));  

      phraseQuery.setSlop(5);  //之間的間隔最大不能超過5個

        對應的查詢語句:title:"lucene 框架"~5

  e. FuzzyQuery模糊查詢(FuzzyQuery(Term term,int maxEdits))

    e.1 maxEdits最小類似度,默認爲2,數字越小,查詢結果越少,取值範圍爲0、一、2,當爲0的時候至關於TermQuery。

      Query query=new FuzzyQuery(new Term("title","lucenX"),2); 

        對應的查詢語句:title:lucenX~2

  f. WildcardQuery通配符搜索

    f.1 *表明0到多個字符,?表明一個單一的字符。

      Query query=new WildcardQuery(new Term("title","lu*n?")); 

        對應的查詢語句是:title:lu*n?

  g. MatchAllDocsQuery搜索所有

    Query query=new MatchAllDocsQuery(); 

      對應的查詢語句是:*:*

5. 排序、過濾、高亮

  a. 這部份內容在demo中備註已經很是詳細,若是你們想去了解,請去github上下載項目自行查看(裏面有詳細備註)。

  b. GitHub地址是:https://github.com/kencery/Lucene_Compass/tree/master/Lucene_5.5

  c. 排序對應分支是:lucene_seven,過濾對應的分支是:lucene_eight,高亮對應的分支是:lucene_six

 

     但願你們能從中間學到東西,若有疑問,請留言或者去GitHub上看LuceneDemo或者添加個人QQ,咱們共同探討。

相關文章
相關標籤/搜索