使用Java的Lucene搜索工具對(duì)檢索結(jié)果進(jìn)行分組和分頁(yè)
使用GroupingSearch對(duì)搜索結(jié)果進(jìn)行分組
Package org.apache.lucene.search.grouping Description
這個(gè)模塊可以對(duì)Lucene的搜索結(jié)果進(jìn)行分組,指定的單值域被聚集到一起。比如,根據(jù)”author“域進(jìn)行分組,“author”域值相同的的文檔分成一個(gè)組。
進(jìn)行分組的時(shí)候需要輸入一些必要的信息:
1、groupField:根據(jù)這個(gè)域進(jìn)行分組。比如,如果你使用“author”域進(jìn)行分組,那么每一個(gè)組里面的書(shū)籍都是同一個(gè)作者。沒(méi)有這個(gè)域的文檔將被分到一個(gè)單獨(dú)的組里面。
2、groupSort:組排序。
3、topNGroups:保留多少組。比如,10表示只保留前10組。
4、groupOffset:對(duì)排在前面的哪些分組組進(jìn)行檢索。比如,3表示返回7個(gè)組(假設(shè)opNGroups等于10)。在分頁(yè)里面很有用,比如每頁(yè)只顯示5個(gè)組。
5、withinGroupSort:組內(nèi)文檔排序。注意:這里和groupSort的區(qū)別
6、withingroupOffset:對(duì)每一個(gè)分組里面的哪些排在前面的文檔進(jìn)行檢索。
使用GroupingSearch 對(duì)搜索結(jié)果分組比較簡(jiǎn)單
GroupingSearch API文檔介紹:
Convenience class to perform grouping in a non distributed environment.
非分布式環(huán)境下分組
WARNING: This API is experimental and might change in incompatible ways in the next release.
這里使用的是4.3.1版本
一些重要的方法:
- GroupingSearch:setCaching(int maxDocsToCache, boolean cacheScores) 緩存
- GroupingSearch:setCachingInMB(double maxCacheRAMMB, boolean cacheScores) 緩存第一次搜索結(jié)果,用于第二次搜索
- GroupingSearch:setGroupDocsLimit(int groupDocsLimit) 指定每組返回的文檔數(shù),不指定時(shí),默認(rèn)返回一個(gè)文檔
- GroupingSearch:setGroupSort(Sort groupSort) 指定分組排序
示例代碼:
1.先看建索引的代碼
public class IndexHelper { private Document document; private Directory directory; private IndexWriter indexWriter; public Directory getDirectory(){ directory=(directory==null)? new RAMDirectory():directory; return directory; } private IndexWriterConfig getConfig() { return new IndexWriterConfig(Version.LUCENE_43, new IKAnalyzer(true)); } private IndexWriter getIndexWriter() { try { return new IndexWriter(getDirectory(), getConfig()); } catch (IOException e) { e.printStackTrace(); return null; } } public IndexSearcher getIndexSearcher() throws IOException { return new IndexSearcher(DirectoryReader.open(getDirectory())); } /** * Create index for group test * @param author * @param content */ public void createIndexForGroup(int id,String author,String content) { indexWriter = getIndexWriter(); document = new Document(); document.add(new IntField("id",id, Field.Store.YES)); document.add(new StringField("author", author, Field.Store.YES)); document.add(new TextField("content", content, Field.Store.YES)); try { indexWriter.addDocument(document); indexWriter.commit(); indexWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }
2.分組:
public class GroupTest public void group(IndexSearcher indexSearcher,String groupField,String content) throws IOException, ParseException { GroupingSearch groupingSearch = new GroupingSearch(groupField); groupingSearch.setGroupSort(new Sort(SortField.FIELD_SCORE)); groupingSearch.setFillSortFields(true); groupingSearch.setCachingInMB(4.0, true); groupingSearch.setAllGroups(true); //groupingSearch.setAllGroupHeads(true); groupingSearch.setGroupDocsLimit(10); QueryParser parser = new QueryParser(Version.LUCENE_43, "content", new IKAnalyzer(true)); Query query = parser.parse(content); TopGroups<BytesRef> result = groupingSearch.search(indexSearcher, query, 0, 1000); System.out.println("搜索命中數(shù):" + result.totalHitCount); System.out.println("搜索結(jié)果分組數(shù):" + result.groups.length); Document document; for (GroupDocs<BytesRef> groupDocs : result.groups) { System.out.println("分組:" + groupDocs.groupValue.utf8ToString()); System.out.println("組內(nèi)記錄:" + groupDocs.totalHits); //System.out.println("groupDocs.scoreDocs.length:" + groupDocs.scoreDocs.length); for (ScoreDoc scoreDoc : groupDocs.scoreDocs) { System.out.println(indexSearcher.doc(scoreDoc.doc)); } } }
3.簡(jiǎn)單的測(cè)試:
public static void main(String[] args) throws IOException, ParseException { IndexHelper indexHelper = new IndexHelper(); indexHelper.createIndexForGroup(1,"紅薯", "開(kāi)源中國(guó)"); indexHelper.createIndexForGroup(2,"紅薯", "開(kāi)源社區(qū)"); indexHelper.createIndexForGroup(3,"紅薯", "代碼設(shè)計(jì)"); indexHelper.createIndexForGroup(4,"紅薯", "設(shè)計(jì)"); indexHelper.createIndexForGroup(5,"覺(jué)先", "Lucene開(kāi)發(fā)"); indexHelper.createIndexForGroup(6,"覺(jué)先", "Lucene實(shí)戰(zhàn)"); indexHelper.createIndexForGroup(7,"覺(jué)先", "開(kāi)源Lucene"); indexHelper.createIndexForGroup(8,"覺(jué)先", "開(kāi)源solr"); indexHelper.createIndexForGroup(9,"散仙", "散仙開(kāi)源Lucene"); indexHelper.createIndexForGroup(10,"散仙", "散仙開(kāi)源solr"); indexHelper.createIndexForGroup(11,"散仙", "開(kāi)源"); GroupTest groupTest = new GroupTest(); groupTest.group(indexHelper.getIndexSearcher(),"author", "開(kāi)源"); } }
4.測(cè)試結(jié)果:
兩種分頁(yè)方式
Lucene有兩種分頁(yè)方式:
1、直接對(duì)搜索結(jié)果進(jìn)行分頁(yè),數(shù)據(jù)量比較少的時(shí)候可以用這種方式,分頁(yè)代碼核心參照:
ScoreDoc[] sd = XXX; // 查詢(xún)起始記錄位置 int begin = pageSize * (currentPage - 1); // 查詢(xún)終止記錄位置 int end = Math.min(begin + pageSize, sd.length); for (int i = begin; i < end && i <totalHits; i++) { //對(duì)搜索結(jié)果數(shù)據(jù)進(jìn)行處理的代碼 }
2、使用searchAfter(...)
Lucene提供了五個(gè)重載方法,可以根據(jù)需要使用
ScoreDoc after:為上次搜索結(jié)果ScoreDoc總量減1;
Query query:查詢(xún)方式
int n:為每次查詢(xún)返回的結(jié)果數(shù),即每頁(yè)的結(jié)果總量
一個(gè)簡(jiǎn)單的使用示例:
//可以使用Map保存必要的搜索結(jié)果 Map<String, Object> resultMap = new HashMap<String, Object>(); ScoreDoc after = null; Query query = XX TopDocs td = search.searchAfter(after, query, size); //獲取命中數(shù) resultMap.put("num", td.totalHits); ScoreDoc[] sd = td.scoreDocs; for (ScoreDoc scoreDoc : sd) { //經(jīng)典的搜索結(jié)果處理 } //搜索結(jié)果ScoreDoc總量減1 after = sd[td.scoreDocs.length - 1]; //保存after用于下次搜索,即下一頁(yè)開(kāi)始 resultMap.put("after", after); return resultMap;
- Java分頁(yè)工具類(lèi)及其使用(示例分享)
- Java Web 簡(jiǎn)單的分頁(yè)顯示實(shí)例代碼
- Java的MyBatis框架中實(shí)現(xiàn)多表連接查詢(xún)和查詢(xún)結(jié)果分頁(yè)
- Java簡(jiǎn)單實(shí)現(xiàn)SpringMVC+MyBatis分頁(yè)插件
- 舉例詳解用Java實(shí)現(xiàn)web分頁(yè)功能的方法
- js前臺(tái)分頁(yè)顯示后端JAVA數(shù)據(jù)響應(yīng)
- Java(基于Struts2) 分頁(yè)實(shí)現(xiàn)代碼
- 使用Jquery+Ajax+Json如何實(shí)現(xiàn)分頁(yè)顯示附JAVA+JQuery實(shí)現(xiàn)異步分頁(yè)
- Java操作MongoDB模糊查詢(xún)和分頁(yè)查詢(xún)
- java分頁(yè)工具類(lèi)的使用方法
相關(guān)文章
String實(shí)例化及static final修飾符實(shí)現(xiàn)方法解析
這篇文章主要介紹了String實(shí)例化及static final修飾符實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09Mybatis自定義類(lèi)型轉(zhuǎn)換器的使用技巧
這篇文章主要介紹了Mybatis自定義類(lèi)型轉(zhuǎn)換器的使用技巧,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04win10安裝JDK14.0.2的詳細(xì)安裝過(guò)程
這篇文章主要介紹了win10安裝JDK14.0.2的詳細(xì)安裝過(guò)程的相關(guān)資料,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09elasticsearch節(jié)點(diǎn)的transport請(qǐng)求發(fā)送處理分析
這篇文章主要為大家介紹了elasticsearch節(jié)點(diǎn)的transport請(qǐng)求發(fā)送處理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Java 如何繞過(guò)迭代器遍歷時(shí)的數(shù)據(jù)修改異常
這篇文章主要介紹了Java 繞過(guò)迭代器遍歷時(shí)的數(shù)據(jù)修改異常的方法,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-02-02SpringCloud整合Consul的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud整合Consul的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01java.io.UnsupportedEncodingException異常的正確解決方法(親測(cè)有效!)
這篇文章主要給大家介紹了關(guān)于java.io.UnsupportedEncodingException異常的正確解決方法,文中介紹的辦法親測(cè)有效,java.io.UnsupportedEncodingException是Java編程語(yǔ)言中的一個(gè)異常類(lèi),表示指定的字符集不被支持,需要的朋友可以參考下2024-02-02