lucene全文搜索之四:創建索引搜索器、6種文檔搜索器實現以及搜索結果分析(結合IKAnalyzer分詞器的搜索器)基於lucene5.5.3
- 2019 年 11 月 1 日
- 筆記
版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/eguid_1/article/details/53088971
前言:
前面幾章已經很詳細的講解了如何創建索引器對索引進行增刪查(沒有更新操作)、如何管理索引目錄以及如何使用分詞器,上一章講解了如何生成索引欄位和創建索引文檔,並把創建的索引文檔保存到索引目錄,到這裡我們已經知道如何建立索引,那麼本章將會詳解如何搜索索引目錄中的索引文檔索以及如何創建索引搜索器和六種文檔搜索器(搜索器)的實現。
luncene5.5.3集合jar包下載地址:http://download.csdn.net/detail/eguid_1/9677589
一、創建索引搜索器
索引搜索器由索引目錄創建,依賴搜索器進行全文搜索,部分搜索器依賴分詞器進行分詞查詢
1、創建索引目錄搜索器(即索引搜索器)
根據索引目錄創建索引搜索(如果有多個索引目錄,那麼需要創建多個索引搜索,分別搜索出結果後再對搜索結果進行合併調整)
/** * 創建索引搜索 * * @param indexReader -索引目錄Reader * @return */ public IndexSearcher createSearch(IndexReader indexReader) { IndexSearcher indexSearch = null; if (indexReader != null) { indexSearch = new IndexSearcher(indexReader); } return indexSearch; } /** * 創建索引搜索 * @param dir -索引目錄 * @return */ public IndexSearcher createSearch(Directory dir) { IndexSearcher indexSearch = null; try { IndexReader indexReader = DirectoryReader.open(dir); indexSearch = new IndexSearcher(indexReader); } catch (IOException e) { } return indexSearch; }
為了方便閱讀,我們把六種搜索器放在最後, 這裡先講如何根據文檔搜索器來搜索結果並且可以實現排序等等搜索結果的調整
2、搜索結果
/** * 搜索 * * @param search * -索引搜索器 * @param query * -查詢器 * @param num * -搜索結果數量 * @return */ public TopDocs search(IndexSearcher search, Query query, int num) { TopDocs topDocs = null; try { topDocs = search.search(query, num); } catch (IOException e) { } return topDocs; } /** * 自定義排序搜索 * * @param search * -索引搜索 * @param query * -查詢器 * @param num * -搜索結果數量 * @param sort * -排序 * @return */ public TopDocs search(IndexSearcher search, Query query, int num, Sort sort) { TopDocs topDocs = null; try { topDocs = search.search(query, num, sort); } catch (IOException e) { } return topDocs; } /** * 搜索 * * @param search * -索引搜索器 * @param query * -查詢器 * @param results * -搜索結果 */ public void search(IndexSearcher search, Query query, Collector results) { try { if (query != null && results != null) search.search(query, results); } catch (IOException e) { } } /** * 按照匹配分數搜索 * * @param search * @param query * @param after * -文檔匹配分數 * @param numHits * -命中數量 * @return */ public TopDocs search(IndexSearcher search, Query query, ScoreDoc after, int numHits) { TopDocs topDocs = null; try { if (query != null && after != null) topDocs = search.searchAfter(after, query, numHits); } catch (IOException e) { } return topDocs; } /** * 按照匹配分數搜索 * * @param search * @param query * @param after * -文檔匹配分數 * @param numHits * -命中數量 * @param sort * 自定義排序 * @return 搜索結果 */ public TopDocs search(IndexSearcher search, Query query, ScoreDoc after, int numHits, Sort sort) { TopDocs topDocs = null; try { if (query != null && after != null && sort != null) topDocs = search.searchAfter(after, query, numHits, sort); } catch (IOException e) { } return topDocs; } /* 以下API已過時不建議再使用 */ public TopDocs search(IndexSearcher search, Query query, Filter filter, int results) { TopDocs topDocs = null; try { topDocs = search.search(query, filter, results); } catch (IOException e) { } return topDocs; } public TopDocs search(IndexSearcher search, Query query, Filter filter, int results, Sort sort) { TopDocs topDocs = null; try { topDocs = search.search(query, filter, results, sort); } catch (IOException e) { } return topDocs; } public TopDocs search(IndexSearcher search, Query query, Filter filter, int results, Sort sort, boolean doDocScores, boolean doMaxScore) { TopDocs topDocs = null; try { topDocs = search.search(query, filter, results, sort, doDocScores, doMaxScore); } catch (IOException e) { } return topDocs; }
二、六種搜索器實現
/** * 創建單詞搜索器 * * @param fieldName * @param key * @return */ public Query createTermQuery(String fieldName, String key) { return new TermQuery(new Term(fieldName, key)); } /** * 創建前綴搜索器 * * @param fieldName * @param key * @return */ public Query createPrefixQeury(String fieldName, String key) { return new PrefixQuery(new Term(fieldName, key)); } /** * 創建範圍搜索器 * * @param fieldName * @param start * @param end * @return */ public Query createNumericRangeQuery(String fieldName, int start, int end) { return NumericRangeQuery.newIntRange(fieldName, start, end, true, true); } /** * 根據分詞器創建條件搜索 * * @param operator * @param analyzer * @param fieldName * @param key * @return * @throws ParseException */ public Query createPhraseQueryByOperator(Operator operator, Analyzer analyzer, String fieldName, String key) throws ParseException { QueryParser qp = new QueryParser(fieldName, analyzer); if (operator != null) { qp.setDefaultOperator(operator); } return qp.parse(key); } /** * 根據分詞器創建模糊搜索 * * @param analyzer * @param fieldName * @param key * @return * @throws ParseException */ public Query createPhraseQuery(Analyzer analyzer, String fieldName, String key) throws ParseException { return createPhraseQueryByOperator(null, analyzer, fieldName, key); } /** * 創建混合搜索器 * * @return */ public BooleanQuery createBooleanQuery() { return new BooleanQuery(); } /** * 添加搜索器到混合搜索器 * * @param booleanQuery * @param occ * @param query */ public void addToBooleanQuery(BooleanQuery booleanQuery, Occur occ, Query query) { if (booleanQuery != null && query != null && occ != null) { booleanQuery.add(query, occ); } }
三、搜索結果解析
public String[] parseQuery(TopDocs topDocs,IndexSearcher search,String fieldName){ int hits = 0; if (topDocs != null && (hits = topDocs.totalHits) > 0) { ScoreDoc[] docs = topDocs.scoreDocs; String[] results = new String[hits]; for (ScoreDoc doc : docs) { try { //通過搜索結果找到對應文檔 Document resultDoc = search.doc(doc.doc); List<IndexableField> list=resultDoc.getFields(); for(IndexableField i:list) { System.out.println("名稱:"+i.name()+",內容:"+i.stringValue()+",權重值:"+i.boost()); } } catch (IOException e) { } } return results; } return null; }
四、測試搜索
Analyzer analyzer=createAnalyzer(false); Directory dir=createDirectory(null, "d:","dir","search"); IndexWriterConfig conf=createIndexConf(analyzer, OpenMode.CREATE_OR_APPEND, false); IndexWriter index=createIndex(dir, conf); //創建一個文檔 Document doc=createDocument(); String[] states = new String[] {"歡迎來到eguid的部落格", "歡迎大家來到eguid的技術部落格", "歡迎大家來到eguid的技術部落格,很開心能和大家一起分享開源技術"}; //創建欄位 Field[] fields=createFields("欄位名", states, TextField.TYPE_STORED, 1.1f); //批量增加欄位到索引文檔 addFiledList(doc, fields); //把索引文檔保存到索引器 index.addDocument(doc); close(index, true); //讀取目錄 IndexReader indexReader=DirectoryReader.open(dir); //創建索引搜索器 IndexSearcher indexSearch=createSearch(indexReader); try { //創建文檔搜索器 Query query=createPhraseQuery(analyzer, "欄位名", "eguid"); //搜索結果 TopDocs topDocs=search(indexSearch, query, 2); parseQuery(topDocs, indexSearch, "欄位名"); //得到TopDocs,這個TopDocs就是一個結果文檔,裡面包含了搜索的結果內容,匹配度等等搜索計算結果參數 } catch (ParseException e) { }
搜索結果:
名稱:欄位名,內容:歡迎來到eguid的部落格,權重值:1.0 名稱:欄位名,內容:歡迎大家來到eguid的技術部落格,權重值:1.0 名稱:欄位名,內容:歡迎大家來到eguid的技術部落格,很開心能和大家一起分享開源技術,權重值:1.0
到這裡,lucene全文搜索的全部功能就全部實現了,而我們需要做的就是根據我們自己的業務對lucene的功能進行組合,從而實現我們的全文搜搜服務。