個人筆記之用,如有錯誤,懇請批評指正。
高亮,多字段查詢,分頁查詢。
分頁查詢,接上
若查詢第二頁,每頁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對象進行高亮返回帶有高亮格式的指定字段值,重新setValue到document中的對應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