Lucene的基本使用

1、全文檢索與Lucene介紹

一、全文檢索java

  將非結構化數據中的一部分信息提取出來,從新組織,使其變得有必定結構,而後對此有必定結構的數據進行搜索,從而達到搜索相對較快的目的。這部分從非結構化數據中提取出而後從新組織的信息,咱們稱之索引。
  這種先創建索引,再對索引進行搜索的過程就叫全文檢索(Full-text Search)。apache

二、Lucene技術工具

  Lucene是apache下的一個開源的全文檢索引擎工具包(類庫)。它的目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能。Lucene提供了完整的查詢引擎和索引引擎,部分文本分析引擎。網站

三、Lucene實現全文檢索的流程spa

全文檢索的流程分爲兩大部分:索引流程、搜索流程。3d

  • 索引流程:即採集數據構建文檔對象分析文檔(分詞)建立索引。
  • 搜索流程:即用戶經過搜索界面輸入建立查詢執行搜索,搜索器從索引庫搜索渲染搜索結果。

Lucene是開發全文檢索功能的工具包,使用時從官方網站下載,並解壓。code

官方網站:http://lucene.apache.org/對象

下載地址:http://archive.apache.org/dist/lucene/java/blog

下載版本:4.10.3索引

JDK要求:1.7以上(從版本4.8開始,不支持1.7如下)

2、建立索引

 1 //建立索引
 2 @Test
 3 public void testIndex() throws IOException {
 4     //1.  採集數據:(jdbc採集數據經過BookDao調用方法獲得結果集)
 5     BookDaoImpl dao = new BookDaoImpl();
 6     List<Book> bookList = dao.queryBookList();
 7 
 8     //2.  遍歷book結果集,組裝Document數據列表
 9     for (Book book : bookList) {
10          Document doc = new Document();
11          //3.  構建Field域,說白了就是將要存儲的數據字段須要用到new TextField對象三個參數的構造方法,book中有多個字段,因此建立多個Field對象。
12          //參數一:域的名稱,可隨意起;參數二:域對應的值;參數三:是否存儲
13          /*Field id = new TextField("id", book.getId().toString(), Field.Store.YES);
14          Field name = new TextField("name",book.getName(), Field.Store.YES);
15          Field price = new TextField("price",book.getPrice().toString(), Field.Store.YES);
16          Field pic = new TextField("pic",book.getPic(), Field.Store.YES);
17          Field description = new TextField("description",book.getDescription(), Field.Store.YES);*/
18 
19          //id不分詞 要索引 要存儲
20          Field id = new StringField("id", book.getId().toString(), Field.Store.YES);
21          // name 要分詞 要索引 要存儲
22          Field name = new TextField("name", book.getName(), Field.Store.YES);
23          // price 要分詞 要索引 要存儲,數字比較特殊
24          Field price = new FloatField("price", book.getPrice(), Field.Store.YES);
25          // pic 不分詞 不索引 要存儲
26          Field pic = new StoredField("pic", book.getPic());
27          // description 要分詞 要索引 不存儲
28          Field description = new TextField("description", book.getDescription(), Field.Store.NO);
29 
30          //4.  將Field域全部對象,添加到文檔對象中。調用Document.add
31          doc.add(id);
32          doc.add(name);
33          doc.add(price);
34          doc.add(pic);
35          doc.add(description);
36 
37          //5.  建立一個標準分詞器(Analyzer與StandardAnalyzer),對文檔中的Field域進行分詞
38          StandardAnalyzer analyzer = new StandardAnalyzer();
39          //6.  指定索引儲存目錄,使用FSDirectory.open()方法。
40          FSDirectory directory = FSDirectory.open(new File("/Users/Shared/index"));
41          //7.  建立IndexWriterConfig對象,直接new,用於接下來建立IndexWriter對象
42          IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
43          //8.  建立IndexWriter對象,直接new
44          IndexWriter writer = new IndexWriter(directory, config);
45          //9.  添加文檔對象到索引庫輸出對象中,使用IndexWriter.addDocuments方法
46          writer.addDocument(doc);
47          //10.  釋放資源IndexWriter.close();
48          writer.close();
49      }
50 }

3、搜索流程

 1 //搜索
 2 @Test
 3 public void testQuery() throws IOException {
 4      // 1.  建立一個Directory對象,FSDirectory.open指定索引庫存放的位置
 5      FSDirectory directory = FSDirectory.open(new File("/Users/Shared/index"));
 6      // 2.  建立一個IndexReader對象,DirectoryReader.open須要指定Directory對象
 7      IndexReader indexReader = DirectoryReader.open(directory);
 8      // 3.  建立一個Indexsearcher對象,直接new,須要指定IndexReader對象
 9      IndexSearcher indexSearcher = new IndexSearcher(indexReader);
10      // 4.  建立一個TermQuery對象,直接new,指定查詢的域和查詢的關鍵詞new Term(域名稱,關鍵詞)
11      TermQuery query = new TermQuery(new Term("name", "java"));
12      // 5.  執行查詢,IndexSearcher.search,須要指定TermQuery對象與查詢排名靠多少名前的記錄數,獲得結果TopDocs
13      TopDocs docs = indexSearcher.search(query, 10);
14      // 6.  遍歷查詢結果並輸出,TopDocs.totalHits總記錄數,topDocs.scoreDocs數據列表,經過scoreDoc.doc獲得惟一id,再經過IndexSearcher.doc(id),獲得文檔對象Document再Document.get(域名稱)獲得結果
15      System.out.println("查詢總記錄數爲:"+docs.totalHits);
16      for (ScoreDoc scoreDoc : docs.scoreDocs) {
17          //獲得文檔
18          int id = scoreDoc.doc;
19          Document doc = indexSearcher.doc(id);
20          System.out.println("id:"+doc.get("id"));
21          System.out.println("name:"+doc.get("name"));
22          System.out.println("price:"+doc.get("price"));
23          System.out.println("pic:"+doc.get("pic"));
24          System.out.println("description:"+doc.get("description"));
25       }
26      // 7.  關閉IndexReader對象
27      indexReader.close();
28 }

4、Field域

 

5、搜索

一、經過Query子類搜索

①經過MatchAllDocsQuery(查詢全部文檔)

1 @Test
2 public void testFindall() throws Exception{
3     //matachalldocsquery
4     Query query = new MatchAllDocsQuery();
5     //建立一個indexSearcher 對象
6     //經過indexSearcher 調用search方法查詢
7     doSearcherBy(query);
8 }

②TermQuery

1 @Test
2 public void testTermQuery() throws IOException {
3   TermQuery termQuery = new TermQuery(new Term("name", "apache"));
4   doSearchBy(termQuery);
5 }

③NumericRangeQuery

 1 @Test
 2 public void testNumbericRange() throws IOException{
 3   //第一個參數:域的名稱
 4   //第二個參數:最小值
 5   //第三個參數:最大值
 6   //第四個參數:是否包含最小值 
 7   //第五個參數:是否包含最大值 
 8   NumericRangeQuery query = NumericRangeQuery.newFloatRange("price", 55f, 60f, false, false);
 9   doSearcherBy(query);
10 }

④BooleanQuery

 1 @Test
 2 publicvoid booleanQuery() throws Exception {
 3   BooleanQuery query = new BooleanQuery();
 4   Query query1 = new TermQuery(new Term("id", "3"));
 5   Query query2 = NumericRangeQuery.newFloatRange("price", 10f, 200f,true, true);
 6   //MUST:查詢條件必須知足,至關於AND
 7   //SHOULD:查詢條件可選,至關於OR
 8   //MUST_NOT:查詢條件不能知足,至關於NOT非
 9   query.add(query1, Occur.MUST);
10   query.add(query2, Occur.SHOULD);
11   System.out.println(query);
12   doSearcherBy(query);
13 }

二、經過QueryParser搜索

①查詢語法

查看語法,Query對象執行的查詢語法可經過System.out.println(query),查看。

第一種簡單的語法:

域名+":"+搜索的關鍵詞 例如:name:java 表示搜索域名爲name ,其關鍵詞爲java的文檔對象。

第二種:查詢全部的文檔

*:*

第三種:數值範圍的語法:

域名+「:」+[數值 TO 數值] 表示數值範圍,而且包括數值。若是不包括數值 用"{}"好比:

price:[55.0 TO 70.0] 等同於 55=< price <=70
price:{55.0 TO 70.0] 等同於 55 < price <=70

  數值範圍類的查詢語法,不支持在queryparser中查詢。語法是沒有錯誤的。在solr中能夠查詢出來。
第四種:組合條件查詢
  Occur.MUST 查詢條件必須知足,至關於and
  +(加號)
  Occur.SHOULD 查詢條件可選,至關於or

  空(不用符號)
  Occur.MUST_NOT 查詢條件不能知足,至關於not非
  -(減號)

  1)+條件1 +條件2:兩個條件之間是而且的關係and
  例如:+filename:apache +content:apache

  2)+條件1 條件2:必須知足第一個條件,忽略第二個條件
  例如:+filename:apache content:apache

  3)條件1 條件2:兩個條件知足其一便可。
  例如:filename:apache content:apache

  4)-條件1 條件2:必須不知足條件1,要知足條件2
  例如:-filename:apache content:apache

第二種寫法:

  • 條件1 AND 條件2
  • 條件1 OR 條件2
  • 條件1 NOT 條件2

②MultiFieldQueryParser

 1 @Test
 2 publicvoidtestMultiFieldQueryParser() throws Exception {
 3   // 能夠指定默認搜索的域是多個
 4   String[] fields = { "name", "description" };
 5   // 建立一個MulitFiledQueryParser對象
 6   QueryParser parser = new MultiFieldQueryParser(fields, new IKAnalyzer());
 7   // 指定查詢語法,若是不指定域,就搜索默認的域
 8   Query query = parser.parse("lucene");
 9   // 二、執行搜索
10   doSearcherBy(query);
11 }
相關文章
相關標籤/搜索