JAVAEE——Lucene基礎:什麼是全文檢索、Lucene實現全文檢索的流程、配置開發環境、索引庫建立與管理

1. 學習計劃

第一天:Lucene的基礎知識java

一、案例分析:什麼是全文檢索,如何實現全文檢索git

二、Lucene實現全文檢索的流程github

a) 建立索引web

b) 查詢索引算法

三、配置開發環境spring

四、建立索引庫sql

五、查詢索引庫數據庫

六、分析器的分析過程apache

a) 測試分析器的分詞效果windows

b) 第三方中文分析器

七、索引庫的維護

a) 添加文檔

b) 刪除文檔

c) 修改文檔

8Lucene的高級查詢Lucene的查詢

a) 使用Query的子類查詢

  1. MatchAllDocsQuery
  2. TermQuery
  3. NumericRangeQuery
  4. BooleanQuery

b) 使用QueryParser

  1. QueryParser
  2. MulitFieldQueryParser

 

 

2. 案例

實現一個文件的搜索功能,經過關鍵字搜索文件,凡是文件名或文件內容包括關鍵字的文件都須要找出來。還能夠根據中文詞語進行查詢,而且須要支持多個條件查詢。

本案例中的原始內容就是磁盤上的文件,以下圖:

 

 

 

3. 需求分析

3.1. 數據庫搜索

數據庫中的搜索很容易實現,一般都是使用sql語句進行查詢,並且能很快的獲得查詢結果。

爲何數據庫搜索很容易?

由於數據庫中的數據存儲是有規律的,有行有列並且數據格式、數據長度都是固定的。

 

3.2. 數據分類

咱們生活中的數據整體分爲兩種:結構化數據和非結構化數據。

結構化數據:指具備固定格式或有限長度的數據,如數據庫,元數據等。

非結構化數據:指不定長或無固定格式的數據,如郵件,word文檔等磁盤上的文件

 

3.3. 非結構化數據查詢方法

(1)順序掃描法(Serial Scanning)

所謂順序掃描,好比要找內容包含某一個字符串的文件,就是一個文檔一個文檔的看,對於每個文檔,從頭看到尾,若是此文檔包含此字符串,則此文檔爲咱們要找的文件,接着看下一個文件,直到掃描完全部的文件。如利用windows的搜索也能夠搜索文件內容,只是至關的慢。

(2)全文檢索(Full-text Search)

將非結構化數據中的一部分信息提取出來,從新組織,使其變得有必定結構,而後對此有必定結構的數據進行搜索,從而達到搜索相對較快的目的。這部分從非結構化數據中提取出的而後從新組織的信息,咱們稱之索引

例如:字典字典的拼音表和部首檢字表就至關於字典的索引,對每個字的解釋是非結構化的,若是字典沒有音節表和部首檢字表,在茫茫辭海中找一個字只能順序掃描。然而字的某些信息能夠提取出來進行結構化處理,好比讀音,就比較結構化,分聲母和韻母,分別只有幾種能夠一一列舉,因而將讀音拿出來按必定的順序排列,每一項讀音都指向此字的詳細解釋的頁數。咱們搜索時按結構化的拼音搜到讀音,而後按其指向的頁數,即可找到咱們的非結構化數據——也即對字的解釋。

這種先創建索引,再對索引進行搜索的過程就叫全文檢索(Full-text Search)

雖然建立索引的過程也是很是耗時的,可是索引一旦建立就能夠屢次使用,全文檢索主要處理的是查詢,因此耗時間建立索引是值得的。

3.4. 如何實現全文檢索

可使用Lucene實現全文檢索。Luceneapache下的一個開放源代碼的全文檢索引擎工具包。提供了完整的查詢引擎和索引引擎,部分文本分析引擎。Lucene的目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能。

 

3.5. 全文檢索的應用場景

對於數據量大、數據結構不固定的數據可採用全文檢索方式搜索,好比百度、Google等搜索引擎、論壇站內搜索、電商網站站內搜索等。

 

4. Lucene實現全文檢索的流程

4.1. 索引和搜索流程圖

 

 

1、綠色表示索引過程,對要搜索的原始內容進行索引構建一個索引庫,索引過程包括:

肯定原始內容即要搜索的內容→採集文檔→建立文檔→分析文檔→索引文檔

 

2、紅色表示搜索過程,從索引庫中搜索內容,搜索過程包括:

用戶經過搜索界面→建立查詢→執行搜索,從索引庫搜索→渲染搜索結果

 

4.2. 建立索引

對文檔索引的過程,將用戶要搜索的文檔內容進行索引,索引存儲在索引庫(index)中。

這裏咱們要搜索的文檔是磁盤上的文本文件,根據案例描述:凡是文件名或文件內容包括關鍵字的文件都要找出來,這裏要對文件名和文件內容建立索引。

 

4.2.1. 得到原始文檔

原始文檔是指要索引和搜索的內容。原始內容包括互聯網上的網頁、數據庫中的數據、磁盤上的文件等。

本案例中的原始內容就是磁盤上的文件,以下圖:

 

 

 

從互聯網上、數據庫、文件系統中等獲取須要搜索的原始信息,這個過程就是信息採集,信息採集的目的是爲了對原始內容進行索引。

Internet上採集信息的軟件一般稱爲爬蟲或蜘蛛,也稱爲網絡機器人,爬蟲訪問互聯網上的每個網頁,將獲取到的網頁內容存儲起來。

Lucene不提供信息採集的類庫,須要本身編寫一個爬蟲程序實現信息採集,也能夠經過一些開源軟件實現信息採集,以下:

Nutchhttp://lucene.apache.org/nutch, Nutchapache的一個子項目,包括大規模爬蟲工具,可以抓取和分辨web網站數據。

jsoup(http://jsoup.org/ ),jsoup 是一款Java HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套很是省力的API,可經過DOMCSS以及相似於jQuery的操做方法來取出和操做數據。

heritrixhttp://sourceforge.net/projects/archive-crawler/files/),Heritrix 是一個由 java 開發的、開源的網絡爬蟲,用戶可使用它來從網上抓取想要的資源。其最出色之處在於它良好的可擴展性,方便用戶實現本身的抓取邏輯。

本案例咱們要獲取磁盤上文件的內容,能夠經過文件流來讀取文本文件的內容,對於pdfdocxls等文件可經過第三方提供的解析工具讀取文件內容,好比Apache POI讀取docxls的文件內容。

 

4.2.2. 建立文檔對象

獲取原始內容的目的是爲了索引,在索引前須要將原始內容建立成文檔(Document),文檔中包括一個一個的域(Field),域中存儲內容。

這裏咱們能夠將磁盤上的一個文件當成一個documentDocument中包括一些Fieldfile_name文件名稱、file_path文件路徑、file_size文件大小、file_content文件內容),以下圖:

 

 

注意:每一個Document能夠有多個Field,不一樣的Document能夠有不一樣的Field,同一個Document能夠有相同的Field(域名和域值都相同)

 

每一個文檔都有一個惟一的編號,就是文檔id

 

4.2.3. 分析文檔

將原始內容建立爲包含域(Field)的文檔(document),須要再對域中的內容進行分析,分析的過程是通過對原始文檔提取單詞、將字母轉爲小寫、去除標點符號、去除停用詞等過程生成最終的語彙單元,能夠將語彙單元理解爲一個一個的單詞。

 

好比下邊的文檔通過分析以下:

原文檔內容:

Lucene is a Java full-text search engine.  Lucene is not a complete

application, but rather a code library and API that can easily be used

to add search capabilities to applications.

 

分析後獲得的語彙單元

lucenejavafullsearchengine。。。。

 

每一個單詞叫作一個Term,不一樣的域中拆分出來的相同的單詞是不一樣的termterm中包含兩部分一部分是文檔的域名,另外一部分是單詞的內容。

例如:文件名中包含apache和文件內容中包含的apache是不一樣的term

4.2.4. 建立索引

對全部文檔分析得出的語彙單元進行索引,索引的目的是爲了搜索,最終要實現只搜索被索引的語彙單元從而找到Document(文檔)。

 

 

 

 

注意:建立索引是對語彙單元索引,經過詞語找文檔,這種索引的結構叫倒排索引結構

傳統方法是根據文件找到該文件的內容,在文件內容中匹配搜索關鍵字,這種方法是順序掃描方法,數據量大、搜索慢。

倒排索引結構是根據內容(詞語)找文檔,以下圖:

 

 

倒排索引結構也叫反向索引結構,包括索引和文檔兩部分,索引即詞彙表,它的規模較小,而文檔集合較大。

 

4.3. 查詢索引

查詢索引也是搜索的過程。搜索就是用戶輸入關鍵字,從索引(index)中進行搜索的過程。根據關鍵字搜索索引,根據索引找到對應的文檔,從而找到要搜索的內容(這裏指磁盤上的文件)。

 

4.3.1. 用戶查詢接口

全文檢索系統提供用戶搜索的界面供用戶提交搜索的關鍵字,搜索完成展現搜索結果。

 

好比:

 

 

 

Lucene不提供製做用戶搜索界面的功能,須要根據本身的需求開發搜索界面。

4.3.2. 建立查詢

用戶輸入查詢關鍵字執行搜索以前須要先構建一個查詢對象,查詢對象中能夠指定查詢要搜索的Field文檔域、查詢關鍵字等,查詢對象會生成具體的查詢語法,

例如:

語法fileName:lucene」表示要搜索Field域的內容爲「lucene」的文檔

 

4.3.3. 執行查詢

搜索索引過程:

根據查詢語法在倒排索引詞典表中分別找出對應搜索詞的索引,從而找到索引所連接的文檔鏈表。

好比搜索語法爲fileName:lucene」表示搜索出fileName域中包含Lucene的文檔。

搜索過程就是在索引上查找域爲fileName,而且關鍵字爲Luceneterm,並根據term找到文檔id列表。

 

 

4.3.4. 渲染結果

以一個友好的界面將查詢結果展現給用戶,用戶根據搜索結果找本身想要的信息,爲了幫助用戶很快找到本身的結果,提供了不少展現的效果,好比搜索結果中將關鍵字高亮顯示,百度提供的快照等。

 

 

 

 

5. 配置開發環境

5.1. Lucene下載

Lucene是開發全文檢索功能的工具包,從官方網站下載Lucene4.10.3,並解壓。

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

版本:lucene4.10.3

Jdk要求:1.7以上

IDEEclipse

 

5.2. 使用的jar

 

 

Lucene包:

lucene-core-4.10.3.jar

lucene-analyzers-common-4.10.3.jar

lucene-queryparser-4.10.3.jar

 

其它:

commons-io-2.4.jar

junit-4.9.jar

 

6. 功能一:建立索引庫

使用indexwriter對象建立索引

6.1. 實現步驟

第一步:建立一個java工程,並導入jar包。

第二步:建立一個indexwriter對象。

  1)指定索引庫的存放位置Directory對象

  2)指定一個分析器,對文檔內容進行分析。

第二步:建立document對象。

第三步:建立field對象,將field添加到document對象中。

第四步:使用indexwriter對象將document對象寫入索引庫,此過程進行索引建立。並將索引和document對象寫入索引庫。

第五步:關閉IndexWriter對象。

6.2. Field域的屬性

是否分析:是否對域的內容進行分詞處理。前提是咱們要對域的內容進行查詢。

是否索引:將Field分析後的詞或整個Field值進行索引,只有索引方可搜索到。

好比:商品名稱、商品簡介分析後進行索引,訂單號、身份證號不用分析但也要索引,這些未來都要做爲查詢條件。

是否存儲:將Field值存儲在文檔中,存儲在文檔中的Field才能夠從Document中獲取

好比:商品名稱、訂單號,凡是未來要從Document中獲取的Field都要存儲。

 

是否存儲的標準:是否要將內容展現給用戶

 

Field

數據類型

Analyzed

是否分析

Indexed

是否索引

Stored

是否存儲

說明

StringField(FieldName, FieldValue,Store.YES))

字符串

N

Y

Y或N

這個Field用來構建一個字符串Field,可是不會進行分析,會將整個串存儲在索引中,好比(訂單號,姓名等)

是否存儲在文檔中用Store.YESStore.NO決定

LongField(FieldName, FieldValue,Store.YES)

Long

Y

Y

Y或N

這個Field用來構建一個Long數字型Field,進行分析和索引,好比(價格)

是否存儲在文檔中用Store.YESStore.NO決定

StoredField(FieldName, FieldValue) 

重載方法,支持多種類型

N

N

Y

這個Field用來構建不一樣類型Field

不分析,不索引,但要Field存儲在文檔中

TextField(FieldName, FieldValue, Store.NO)

TextField(FieldName, reader)

 

字符串

Y

Y

Y或N

若是是一個Reader, lucene猜想內容比較多,會採用Unstored的策略.

 

6.3. 代碼實現 

 

//建立索引
    @Test
    public void createIndex() throws Exception {
        
        //指定索引庫存放的路徑
        //D:\temp\0108\index
        Directory directory = FSDirectory.open(new File("D:\\temp\\0108\\index"));
        //索引庫還能夠存放到內存中
        //Directory directory = new RAMDirectory();
        //建立一個標準分析器
        Analyzer analyzer = new StandardAnalyzer();
        //建立indexwriterCofig對象
        //第一個參數: Lucene的版本信息,能夠選擇對應的lucene版本也可使用LATEST
        //第二根參數:分析器對象
        IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
        //建立indexwriter對象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        //原始文檔的路徑D:\傳智播客\01.課程\04.lucene\01.參考資料\searchsource
        File dir = new File("D:\\傳智播客\\01.課程\\04.lucene\\01.參考資料\\searchsource");
        for (File f : dir.listFiles()) {
            //文件名
            String fileName = f.getName();
            //文件內容
            String fileContent = FileUtils.readFileToString(f);
            //文件路徑
            String filePath = f.getPath();
            //文件的大小
            long fileSize  = FileUtils.sizeOf(f);
            //建立文件名域
            //第一個參數:域的名稱
            //第二個參數:域的內容
            //第三個參數:是否存儲
            Field fileNameField = new TextField("filename", fileName, Store.YES);
            //文件內容域
            Field fileContentField = new TextField("content", fileContent, Store.YES);
            //文件路徑域(不分析、不索引、只存儲)
            Field filePathField = new StoredField("path", filePath);
            //文件大小域
            Field fileSizeField = new LongField("size", fileSize, Store.YES);
            
            //建立document對象
            Document document = new Document();
            document.add(fileNameField);
            document.add(fileContentField);
            document.add(filePathField);
            document.add(fileSizeField);
            //建立索引,並寫入索引庫
            indexWriter.addDocument(document);
        }
        //關閉indexwriter
        indexWriter.close();
    }

 

 


6.4. 
使用Luke工具查看索引文件 

 

 

 

7. 功能二:查詢索引

7.1. 實現步驟

第一步:建立一個Directory對象,也就是索引庫存放的位置。

第二步:建立一個indexReader對象,須要指定Directory對象。

第三步:建立一個indexsearcher對象,須要指定IndexReader對象

第四步:建立一個TermQuery對象,指定查詢的域和查詢的關鍵詞。

第五步:執行查詢。

第六步:返回查詢結果。遍歷查詢結果並輸出。

第七步:關閉IndexReader對象

7.2. IndexSearcher搜索方法

 

方法

說明

indexSearcher.search(query, n)

根據Query搜索,返回評分最高的n條記錄

indexSearcher.search(query, filter, n)

根據Query搜索,添加過濾策略,返回評分最高的n條記錄

indexSearcher.search(query, n, sort)

根據Query搜索,添加排序策略,返回評分最高的n條記錄

indexSearcher.search(booleanQuery, filter, n, sort)

根據Query搜索,添加過濾策略,添加排序策略,返回評分最高的n條記錄

 

7.3. 代碼實現

 

//查詢索引庫
    @Test
    public void searchIndex() throws Exception {
        //指定索引庫存放的路徑
        //D:\temp\0108\index
        Directory directory = FSDirectory.open(new File("D:\\temp\\0108\\index"));
        //建立indexReader對象
        IndexReader indexReader = DirectoryReader.open(directory);
        //建立indexsearcher對象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        //建立查詢
        Query query = new TermQuery(new Term("filename", "apache"));
        //執行查詢
        //第一個參數是查詢對象,第二個參數是查詢結果返回的最大值
        TopDocs topDocs = indexSearcher.search(query, 10);
        //查詢結果的總條數
        System.out.println("查詢結果的總條數:"+ topDocs.totalHits);
        //遍歷查詢結果
        //topDocs.scoreDocs存儲了document對象的id
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            //scoreDoc.doc屬性就是document對象的id
            //根據document的id找到document對象
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("filename"));
            //System.out.println(document.get("content"));
            System.out.println(document.get("path"));
            System.out.println(document.get("size"));
        }
        //關閉indexreader對象
        indexReader.close();
    }

 


 
7.4. TopDocs

Lucene搜索結果可經過TopDocs遍歷,TopDocs類提供了少許的屬性,以下:

 

方法或屬性

說明

totalHits

匹配搜索條件的總記錄數

scoreDocs

頂部匹配記錄

 

注意:

Search方法須要指定匹配記錄數量nindexSearcher.search(query, n)

TopDocs.totalHits:是匹配索引庫中全部記錄的數量

TopDocs.scoreDocs:匹配相關度高的前邊記錄數組,scoreDocs的長度小於等於search方法指定的參數n

 

8. 功能三:支持中文分詞

8.1. 分析器(Analyzer)的執行過程

以下圖是語彙單元的生成過程:

 

 

 

 

從一個Reader字符流開始,建立一個基於ReaderTokenizer分詞器,通過三個TokenFilter生成語彙單元Tokens

要看分析器的分析效果,只須要看Tokenstream中的內容就能夠了。每一個分析器都有一個方法tokenStream,返回一個tokenStream對象。

 

8.2. 分析器的分詞效果

//查看標準分析器的分詞效果
    public void testTokenStream() throws Exception {
        //建立一個標準分析器對象
        Analyzer analyzer = new StandardAnalyzer();
        //得到tokenStream對象
        //第一個參數:域名,能夠隨便給一個
        //第二個參數:要分析的文本內容
        TokenStream tokenStream = analyzer.tokenStream("test", "The Spring Framework provides a comprehensive programming and configuration model.");
        //添加一個引用,能夠得到每一個關鍵詞
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
        //添加一個偏移量的引用,記錄了關鍵詞的開始位置以及結束位置
        OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
        //將指針調整到列表的頭部
        tokenStream.reset();
        //遍歷關鍵詞列表,經過incrementToken方法判斷列表是否結束
        while(tokenStream.incrementToken()) {
            //關鍵詞的起始位置
            System.out.println("start->" + offsetAttribute.startOffset());
            //取關鍵詞
            System.out.println(charTermAttribute);
            //結束位置
            System.out.println("end->" + offsetAttribute.endOffset());
        }
        tokenStream.close();
    }

 


8.3. 
中文分析器 

8.3.1. Lucene自帶中文分詞器

l StandardAnalyzer:

單字分詞:就是按照中文一個字一個字地進行分詞。如:「我愛中國」
效果:愛」

l CJKAnalyzer

二分法分詞:按兩個字進行切分。如:中國人,效果:是」中國「國人」

 

上邊兩個分詞器沒法知足需求。

l SmartChineseAnalyzer

對中文支持較好,但擴展性差,擴展詞庫,禁用詞庫和同義詞庫等很差處理

8.3.2. 第三方中文分析器

  • paoding: 庖丁解牛最新版在 https://code.google.com/p/paoding/ 中最多支持Lucene 3.0,且最新提交的代碼在 2008-06-03,在svn中最新也是2010年提交,已通過時,不予考慮。
  • mmseg4j:最新版已從 https://code.google.com/p/mmseg4j/ 移至 https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代碼是2014年6月,從09年~14年一共有:18個版本,也就是一年幾乎有3個大小版本,有較大的活躍度,用了mmseg算法。
  • IK-analyzer: 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10從2006年12月推出1.0版開始, IKAnalyzer已經推出了4個大版本。最初,它是以開源項目Luence爲應用主體的,結合詞典分詞和文法分析算法的中文分詞組件。從3.0版本開 始,IK發展爲面向Java的公用分詞組件,獨立於Lucene項目,同時提供了對Lucene的默認優化實現。在2012版本中,IK實現了簡單的分詞 歧義排除算法,標誌着IK分詞器從單純的詞典分詞向模擬語義分詞衍化。 可是也就是2012年12月後沒有在更新。
  • ansj_seg:最新版本在 https://github.com/NLPchina/ansj_seg tags僅有1.1版本,從2012年到2014年更新了大小6次,可是做者本人在2014年10月10日說明:「可能我之後沒有精力來維護ansj_seg了」,如今由」nlp_china」管理。2014年11月有更新。並未說明是否支持Lucene,是一個由CRF(條件隨機場)算法所作的分詞算法。
  • imdict-chinese-analyzer:最新版在 https://code.google.com/p/imdict-chinese-analyzer/  最新更新也在2009年5月,下載源碼,不支持Lucene 4.10 。是利用HMM(隱馬爾科夫鏈)算法。
  • Jcseg:最新版本在git.oschina.net/lionsoul/jcseg,支持Lucene 4.10,做者有較高的活躍度。利用mmseg算法。

8.3.3. IKAnalyzer

 

 

使用方法:

第一步:把jar包添加到工程中

第二步:把配置文件和擴展詞典和停用詞詞典添加到classpath

 

意:mydict.dicext_stopword.dic文件的格式爲UTF-8,注意是BOM UTF-8 編碼

 

使用EditPlus.exe保存爲BOM UTF-8 編碼格式,以下圖:

 

 

8.4. Analyzer使用時機

8.4.1. 索引時使用Analyzer

輸入關鍵字進行搜索,當須要讓該關鍵字與文檔域內容所包含的詞進行匹配時須要對文檔域內容進行分析,須要通過Analyzer分析器處理生成語彙單元(Token)。分析器分析的對象是文檔中的Field域。當Field的屬性tokenized(是否分詞)爲true時會對Field值進行分析,以下圖:

 

對於一些Field能夠不用分析:

1、不做爲查詢條件的內容,好比文件路徑

2、不是匹配內容中的詞而匹配Field的總體內容,好比訂單號、身份證號等。

 

8.4.2. 搜索時使用Analyzer

對搜索關鍵字進行分析和索引分析同樣,使用Analyzer對搜索關鍵字進行分析、分詞處理,使用分析後每一個詞語進行搜索。好比:搜索關鍵字:spring web ,通過分析器進行分詞,得出:spring  web拿詞去索引詞典表查找 ,找到索引連接到Document,解析Document內容。

對於匹配總體Field域的查詢能夠在搜索時不分析,好比根據訂單號、身份證號查詢等。

 

注意:搜索使用的分析器要和索引使用的分析器一致。

 

9. 功能四:索引庫的維護

9.1. 索引庫的添加

9.1.1. 步驟

向索引庫中添加document對象。

第一步:先建立一個indexwriter對象

第二步:建立一個document對象

第三步:把document對象寫入索引庫

第四步:關閉indexwriter

 

9.1.2. 代碼實現

//添加索引
    @Test
    public void addDocument() throws Exception {
        //索引庫存放路徑
        Directory directory = FSDirectory.open(new File("D:\\temp\\0108\\index"));
        
        IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
        //建立一個indexwriter對象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        //建立一個Document對象
        Document document = new Document();
        //向document對象中添加域。
        //不一樣的document能夠有不一樣的域,同一個document能夠有相同的域。
        document.add(new TextField("filename", "新添加的文檔", Store.YES));
        document.add(new TextField("content", "新添加的文檔的內容", Store.NO));
        document.add(new TextField("content", "新添加的文檔的內容第二個content", Store.YES));
        document.add(new TextField("content1", "新添加的文檔的內容要能看到", Store.YES));
        //添加文檔到索引庫
        indexWriter.addDocument(document);
        //關閉indexwriter
        indexWriter.close();
        
    }

 


9.2. 
索引庫刪除 

9.2.1. 刪除所有

//刪除所有索引
    @Test
    public void deleteAllIndex() throws Exception {
        IndexWriter indexWriter = getIndexWriter();
        //刪除所有索引
        indexWriter.deleteAll();
        //關閉indexwriter
        indexWriter.close();
    }

說明:將索引目錄的索引信息所有刪除,直接完全刪除,沒法恢復。 

 此方法慎用!!

 

9.2.2. 指定查詢條件刪除

//根據查詢條件刪除索引
    @Test
    public void deleteIndexByQuery() throws Exception {
        IndexWriter indexWriter = getIndexWriter();
        //建立一個查詢條件
        Query query = new TermQuery(new Term("filename", "apache"));
        //根據查詢條件刪除
        indexWriter.deleteDocuments(query);
        //關閉indexwriter
        indexWriter.close();
    }

 

9.3. 索引庫的修改 

原理就是先刪除後添加。

//修改索引庫
    @Test
    public void updateIndex() throws Exception {
        IndexWriter indexWriter = getIndexWriter();
        //建立一個Document對象
        Document document = new Document();
        //向document對象中添加域。
        //不一樣的document能夠有不一樣的域,同一個document能夠有相同的域。
        document.add(new TextField("filename", "要更新的文檔", Store.YES));
        document.add(new TextField("content", "2013年11月18日 - Lucene 簡介 Lucene 是一個基於 Java 的全文信息檢索工具包,它不是一個完整的搜索應用程序,而是爲你的應用程序提供索引和搜索功能。", Store.YES));
        indexWriter.updateDocument(new Term("content", "java"), document);
        //關閉indexWriter
        indexWriter.close();
    }

 


10. 
Lucene索引庫查詢(重點) 

對要搜索的信息建立Query查詢對象,Lucene會根據Query查詢對象生成最終的查詢語法,相似關係數據庫Sql語法同樣Lucene也有本身的查詢語法,好比:「name:lucene」表示查詢Fieldname爲「lucene」的文檔信息。

可經過兩種方法建立查詢對象:

1)使用Lucene提供Query子類

Query是一個抽象類,lucene提供了不少查詢對象,好比TermQuery項精確查詢,NumericRangeQuery數字範圍查詢等。

以下代碼:

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

 

2)使用QueryParse解析查詢表達式

QueryParse會將用戶輸入的查詢表達式解析成Query對象實例。

以下代碼:

    QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
        Query query = queryParser.parse("name:lucene");

 

 

10.1. 使用query的子類查詢

10.1.1. MatchAllDocsQuery

使用MatchAllDocsQuery查詢索引目錄中的全部文檔

@Test
    public void testMatchAllDocsQuery() throws Exception {
        IndexSearcher indexSearcher = getIndexSearcher();
        //建立查詢條件
        Query query = new MatchAllDocsQuery();
        //執行查詢
        printResult(query, indexSearcher);
    }

 


10.1.2. 
TermQuery 

TermQuery,經過項查詢,TermQuery不使用分析器因此建議匹配不分詞的Field域查詢,好比訂單號、分類ID號等。

指定要查詢的域和要查詢的關鍵詞。

//使用Termquery查詢
    @Test
    public void testTermQuery() throws Exception {
        IndexSearcher indexSearcher = getIndexSearcher();
        //建立查詢對象
        Query query = new TermQuery(new Term("content", "lucene"));
        //執行查詢
        TopDocs topDocs = indexSearcher.search(query, 10);
        //共查詢到的document個數
        System.out.println("查詢結果總數量:" + topDocs.totalHits);
        //遍歷查詢結果
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("filename"));
            //System.out.println(document.get("content"));
            System.out.println(document.get("path"));
            System.out.println(document.get("size"));
        }
        //關閉indexreader
        indexSearcher.getIndexReader().close();
    }

 


10.1.3. 
NumericRangeQuery 

能夠根據數值範圍查詢。

//數值範圍查詢
    @Test
    public void testNumericRangeQuery() throws Exception {
        IndexSearcher indexSearcher = getIndexSearcher();
        //建立查詢
        //參數:
        //1.域名
        //2.最小值
        //3.最大值
        //4.是否包含最小值
        //5.是否包含最大值
        Query query = NumericRangeQuery.newLongRange("size", 1l, 1000l, true, true);
        //執行查詢
        printResult(query, indexSearcher);
    }

 


10.1.4. 
BooleanQuery 

能夠組合查詢條件。

//組合條件查詢
    @Test
    public void testBooleanQuery() throws Exception {
        IndexSearcher indexSearcher = getIndexSearcher();
        //建立一個布爾查詢對象
        BooleanQuery query = new BooleanQuery();
        //建立第一個查詢條件
        Query query1 = new TermQuery(new Term("filename", "apache"));
        Query query2 = new TermQuery(new Term("content", "apache"));
        //組合查詢條件
        query.add(query1, Occur.MUST);
        query.add(query2, Occur.MUST);
        //執行查詢
        printResult(query, indexSearcher);
    }

Occur.MUST:必須知足此條件,至關於and 

Occur.SHOULD:應該知足,可是不知足也能夠,至關於or

Occur.MUST_NOT:必須不知足。至關於not

 

 

10.2. 使用queryparser查詢

經過QueryParser也能夠建立QueryQueryParser提供一個Parse方法,此方法能夠直接根據查詢語法來查詢。Query對象執行的查詢語法可經過System.out.println(query);查詢。

須要使用到分析器。建議建立索引時使用的分析器和查詢索引時使用的分析器要一致。

 

10.2.1. QueryParser

須要加入queryParser依賴的jar包。

 

 

1.1.1.1 程序實現

@Test
    public void testQueryParser() throws Exception {
        IndexSearcher indexSearcher = getIndexSearcher();
        //建立queryparser對象
        //第一個參數默認搜索的域
        //第二個參數就是分析器對象
        QueryParser queryParser = new QueryParser("content", new IKAnalyzer());
        Query query = queryParser.parse("Lucene是java開發的");
        //執行查詢
        printResult(query, indexSearcher);
    }

 


1.1.1.2 
查詢語法 

1、基礎的查詢語法,關鍵詞查詢:

域名+「:」+搜索的關鍵字

例如:content:java

二、範圍查詢

域名+:+[最小值 TO 最大值]

例如:size:[1 TO 1000]

範圍查詢在lucene中支持數值類型,不支持字符串類型。在solr中支持字符串類型。

三、組合條件查詢

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

Occur.MUST 查詢條件必須知足,至關於and

+(加號)

Occur.SHOULD 查詢條件可選,至關於or

 

空(不用符號)

Occur.MUST_NOT 查詢條件不能知足,至關於not非

-(減號)

 

第二種寫法:

條件1 AND 條件2

條件1 OR 條件2

條件1 NOT 條件2

 

10.2.2. MultiFieldQueryParser

能夠指定多個默認搜索域

@Test
    public void testMultiFiledQueryParser() throws Exception {
        IndexSearcher indexSearcher = getIndexSearcher();
        //能夠指定默認搜索的域是多個
        String[] fields = {"filename", "content"};
        //建立一個MulitFiledQueryParser對象
        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());
        Query query = queryParser.parse("java AND apache");
        System.out.println(query);
        //執行查詢
        printResult(query, indexSearcher);
        
    }
相關文章
相關標籤/搜索