Lucene教程--维护索引、查询对象和相关度排序
1?索引維護
1.1?添加索引
步驟:
1)創建存放索引的目錄Directory
2)創建索引器配置管理類IndexWriterConfig
3)使用索引目錄和配置管理類創建索引器
4)使用索引器將Document寫到索引文件中
代碼:
// 定義索引存儲目錄Directory directory = FSDirectory.open(new File(indexFolder));//標準分析器Analyzer standardAnalyzer = new StandardAnalyzer();IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_4_10_3,standardAnalyzer);// 定義索引操作對象IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);//遍歷目錄下的文檔,創建DocumentList<Document> docs = IndexUtils.file2Document(indexSource);// 遍歷目錄 下的文件生成的文檔,調用indexWriter方法創建索引for (Document document : docs) {indexWriter.addDocument(document);}// 索引操作流關閉indexWriter.close();1.2?刪除索引
1)刪除符合條件的索引
// 索引目錄Directory directory = FSDirectory.open(new File(indexFolder));// 定義索引操作對象IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_4_10_3,new StandardAnalyzer()));// 刪除索引,文件名稱等于“springmvc.txt”的索引刪除indexWriter.deleteDocuments(new Term("fileName", "springmvc.txt"));//索引刪除后無法恢復indexWriter.commit();// 關閉索引操作流indexWriter.close();說明:根據Term項刪除索引,滿足條件的將全部刪除,建議參照關系數據庫基于主鍵刪除方式,所以在創建索引時需要創建一個主鍵Field,刪除時根據此主鍵Field刪除。
索引刪除后將放在Lucene的回收站中,Lucene3.X版本可以恢復刪除的文檔,3.X之后無法恢復。
2)刪除全部索引
// 索引目錄Directory directory = FSDirectory.open(new File(indexFolder));// 定義索引操作對象IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_4_10_3,new StandardAnalyzer()));//刪除全部索引indexWriter.deleteAll();說明:將索引目錄的索引信息全部刪除,直接徹底刪除,無法恢復。
1.3?更新索引
// 索引目錄Directory directory = FSDirectory.open(new File(indexFolder));// 定義索引操作對象IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_4_10_3,new StandardAnalyzer()));// 創建更新文檔Document doc_update = new Document();Field field_fileName = new TextField("fileName", "springmvc.txt",Store.YES);doc_update.add(field_fileName);// 根據條件更新索引,將fileName等于“springmvc_test.txt”的更新為上邊的文檔// 更新的機制 是先刪除再添加,如果原根據fileName沒有找到“springmvc_test.txt”,則添加新文檔indexWriter.updateDocument(new Term("fileName", "springmvc_test.txt"),doc_update);//提交indexWriter.commit();//關閉indexWriter.close();說明:更新索引是先刪除再添加,建議對更新需求采用此方法并且要保證對已存在的索引執行更新,可以先查詢出來,確定更新記錄存在執行更新操作。
2?Query和QueryParser
2.1?創建查詢的兩種方法
創建查詢
對要搜索的信息創建Query查詢對象,Lucene會根據Query查詢對象生成最終的查詢語法,類似關系數據庫Sql語法一樣Lucene也有自己的查詢語法,比如:“name:lucene”表示查詢Field的name為“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");2.2?通過Query?搜索
2.2.1?TermQuery
TermQuery,通過項查詢,TermQuery不使用分析器所以建議匹配不分詞的Field域查詢,比如訂單號、分類ID號等。
//創建查詢對象Query query = new TermQuery(new Term("fileName", "springmvc_test.txt"));//搜索索引 目錄Directory directory = FSDirectory.open(new File(indexFolder));//定義IndexReaderIndexReader reader = DirectoryReader.open(directory);//創建indexSearcherIndexSearcher indexSearcher = new IndexSearcher(reader);//執行搜索TopDocs topDocs = indexSearcher.search(query, 100);2.2.2?NumericRangeQuery
NumericRangeQuery,指定數字范圍查詢,如下:
//文件大小在0到1024的文件NumericRangeQuery<Long> numericRangeQuery = NumericRangeQuery.newLongRange("fileSize", 0l, 1024l, true, true);2.2.3?BooleanQuery
BooleanQuery,布爾查詢,實現組合條件查詢,如下:
// 數字范圍查詢NumericRangeQuery<Long> numericRangeQuery = NumericRangeQuery.newLongRange("fileSize", 0l, 1024l, true, true);//定義Boolean查詢BooleanQuery booleanQuery = new BooleanQuery();//必須滿足fileSize在0到1024范圍的條件booleanQuery.add(numericRangeQuery, Occur.MUST);//根據文件名搜索Query query = new TermQuery(new Term("fileName", "springmvc.txt"));//不查詢文件名為“springmvc_test.txt”booleanQuery.add(query, Occur.MUST);IndexReader reader = DirectoryReader.open(directory);IndexSearcher searcher = new IndexSearcher(reader);TopDocs topDocs = searcher.search(booleanQuery, 100);說明:
Occur.MUST 查詢條件必須滿足,相當于and
Occur.SHOULD 查詢條件可選,相當于or
Occur.MUST_NOT 查詢條件不能滿足,相當于not非
2.2.4 MatchAllDocsQuery
使用MatchAllDocsQuery查詢索引目錄中的所有文檔,如果只存在過濾而沒有查詢條件時可以使用此類定義Query,如下:
//查詢全部文檔Query query = new MatchAllDocsQuery();2.3?通過QueryParser搜索
通過QueryParser也可以創建Query,QueryParser提供一個Parse方法,此方法可以直接根據查詢語法來查詢。Query對象執行的查詢語法可通過System.out.println(query);查詢。
Lucene查詢語法官方介紹:
http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html
2.3.1?QueryParser查詢
QueryParser使用方法:
?
//f是默認搜索的域QueryParser queryParser = new QueryParser("f", analyzer);// 指定查詢語法 ,如果不指定fileName就搜索默認的域Query query2 = queryParser.parse("fileName:springmvc.txt");或:Query query2 = queryParser.parse("spring AND web");上邊介紹的基于類的查詢方法,使用QueryParser可用下邊的查詢語法 實現,
項查詢:
FieldName?:?value
范圍查詢:
FieldName:[min?TO max]
注意:QueryParse不支持對數字范圍的搜索,它支持字符串范圍。數字范圍搜索建議使用NumericRangeQuery。
組合查詢:
上邊BooleanQuery例子的查詢表達式如下:
+fileSize:[0 TO 1024] +fileName:springmvc.txt
上邊的表達式表示fileSize的大小在0和1024之間且fileName為“springmvc.txt”,必須滿足的條件使用+(加號)表示。
?
與BooleanQuery中Occur對應的符號如下:
| Occur.MUST 查詢條件必須滿足,相當于and | +(加號) |
| Occur.SHOULD 查詢條件可選,相當于or | 空(不用符號) |
| Occur.MUST_NOT 查詢條件不能滿足,相當于not非 | -(減號) |
?
關鍵字查詢
AND:關鍵字1 ?AND 關鍵字2
兩個關鍵字都匹配上條件滿足。
OR:關鍵字1 ?OR 關鍵字2
兩個關鍵字匹配一個條件滿足
?
NOT:關鍵字1??NOT ?關鍵字2
關鍵字1滿足,關鍵字2不滿足
2.3.2?MultiFieldQueryParser組合域查詢
通過MuliFieldQueryParse對多個域查詢,比如商品信息查詢,輸入關鍵字需要從商品名稱和商品內容中查詢。
代碼:
//設置組合查詢域String[] fields = {"fileName","fileContent"};//創建查詢解析器QueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());//查詢文件名、文件內容中包括“java”關鍵字的文檔Query query = queryParser.parse("java");3?相關度排序
3.1什么是相關度排序
相關度排序是查詢結果按照與查詢關鍵字的相關性進行排序,越相關的越靠前。比如搜索“Lucene”關鍵字,與該關鍵字最相關的文章應該排在前邊。
3.2?相關度打分
Lucene對查詢關鍵字和索引文檔的相關度進行打分,得分高的就排在前邊。如何打分呢?Lucene是在用戶進行檢索時實時根據搜索的關鍵字計算出來的,分兩步:
1)計算出詞(Term)的權重
2)根據詞的權重值,采用空間向量模型算法計算文檔相關度得分。
什么是詞的權重?
通過索引部分的學習明確索引的最小單位是一個Term(索引詞典中的一個詞),搜索也是要從Term中搜索,再根據Term找到文檔,Term對文檔的重要性稱為權重,影響Term權重有兩個因素:
Term Frequency (tf):
指此Term在此文檔中出現了多少次。tf 越大說明越重要。
詞(Term)在文檔中出現的次數越多,說明此詞(Term)對該文檔越重要,如“Lucene”這個詞,在文檔中出現的次數很多,說明該文檔主要就是講Lucene技術的。
Document Frequency (df)
即有多少文檔包含次Term。df 越大說明越不重要。
比如,在一篇英語文檔中,this出現的次數更多,就說明越重要嗎?不是的,有越多的文檔包含此詞(Term), 說明此詞(Term)太普通,不足以區分這些文檔,因而重要性越低。
3.3?設置boost影響打分結果
boost是一個加權值(默認加權值為1.0f),它可以影響權重的計算。
在索引時對某個文檔的Field域設置加權值高,在搜索時匹配到這個Field就可能排在前邊。
lucene在執行搜索時對某個域進行加權,在進行組合域查詢時,匹配到加權值高的域最后計算的相關度得分就高。
3.3.1 索引時設置boost加權值
如果希望某些文檔更重要,當此文檔中包含所要查詢的詞則應該得分較高,這樣相關度排序可以排在前邊,可以在創建索引時設定文檔中某些域(Field)的boost值來實現,如果不進行設定,則Field Boost默認為1.0f。一旦設定,除非刪除此文檔,否則無法改變。
代碼:
field.?setBoost(XXXf);?XXX即權值。
測試:
可以將springmvc.txt的file_content加權值設置為10.0f,結果搜索spring時如果內容可以匹配到關鍵字就可以把springmvc.txt文件排在前邊。
代碼:
索引時設置boost加權值:
//設置加權值if(file_name.equals("springmvc.txt")){//設置比默認值 1.0大的field_file_content.setBoost(20.0f);}if(file_name.equals("spring_README.txt")){//設置比默認值 1.0大的field_file_content.setBoost(30.0f);}//向文檔中添加Fielddocument.add(field_file_content);搜索時:
// 設置組合查詢域,如果匹配到一個域就返回記錄String[] fields = { "file_content" };//設置評分,文件名稱中包括關鍵字的評分高/*Map<String,Float> boosts = new HashMap<String,Float>();boosts.put("file_content", 3.0f);*/// 創建查詢解析器QueryParser queryParser = new MultiFieldQueryParser(fields,new StandardAnalyzer());// 查詢文件名、文件內容中包括“java”關鍵字的文檔Query query = queryParser.parse("spring");TopDocs topDocs = indexSearcher.search(query, 100);ScoreDoc[] scoreDocs = topDocs.scoreDocs;結果:
springmvc.txt排在最前邊
3.3.2?搜索時設置boost加權值
在執行搜索時對某個域進行加權,在進行組合域查詢時,匹配到加權值高的域最后計算的相關度得分就高。通常把標題、書名等域的加權值設置高點。
//設置組合查詢域String[] fields = {"file_name","file_content"};//設置評分,文件名稱中包括關鍵字的評分高Map<String,Float> boosts = new HashMap<String,Float>();boosts.put("file_name", 10.0f);//創建查詢解析器QueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer(), boosts);//查詢文件名、文件內容中包括“springmvc.txt”關鍵字的文檔,由于設置了文件名稱域的加權值高,所以名稱中匹配到關鍵字的應該排在前邊Query query = queryParser.parse("springmvc.txt");測試:
搜索springmvc.txt,由于文件名中為springmvc.txt應該讓它排在前邊,內容中有springmvc.txt應該排在后邊。
springmvc.txt:
測試結果它應該排在前邊
spring_README.txt
內容中包括springmvc.txt,也能匹配到但要排在后邊。
代碼:
//設置評分,文件名稱中包括關鍵字的評分高Map<String,Float> boosts = new HashMap<String,Float>();boosts.put("file_name", 30.0f);// 創建查詢解析器QueryParser queryParser = new MultiFieldQueryParser(fields,new StandardAnalyzer(),boosts);// 查詢文件名、文件內容中包括“java”關鍵字的文檔Query query = queryParser.parse("springmvc.txt");TopDocs topDocs = indexSearcher.search(query, 100);ScoreDoc[] scoreDocs = topDocs.scoreDocs;總結
以上是生活随笔為你收集整理的Lucene教程--维护索引、查询对象和相关度排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Lucene教程--Analyzer分析
- 下一篇: hibernate教程--事务处理详解