上篇博文《Lucene5学习之创建索引入门示例》里我们创建了索引,现在我们来编写测试代码来查询索引,具体代码如下:
package com.yida.framework.lucene5.core; import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.FSDirectory; import com.yida.framework.lucene5.util.Page; /** * Lucene搜索第一个示例 * @author Lanxiaowei * */ public class SearchFirstTest { public static void main(String[] args) throws ParseException, IOException { //参数定义 String directoryPath = "D:/lucenedir"; String fieldName = "contents"; String queryString = "mount"; int currentPage = 1; int pageSize = 10; Page<Document> page = pageQuery(fieldName, queryString, directoryPath, currentPage, pageSize); if(page == null || page.getItems() == null || page.getItems().size() == 0) { System.out.println("No results found."); return; } for(Document doc : page.getItems()) { String path = doc.get("path"); String content = doc.get("contents"); System.out.println("path:" + path); System.out.println("contents:" + content); } } /** * 创建索引阅读器 * @param directoryPath 索引目录 * @return * @throws IOException 可能会抛出IO异常 */ public static IndexReader createIndexReader(String directoryPath) throws IOException { return DirectoryReader.open(FSDirectory.open(Paths.get(directoryPath, new String[0]))); } /** * 创建索引查询器 * @param directoryPath 索引目录 * @return * @throws IOException */ public static IndexSearcher createIndexSearcher(String directoryPath) throws IOException { return new IndexSearcher(createIndexReader(directoryPath)); } /** * 创建索引查询器 * @param reader * @return */ public static IndexSearcher createIndexSearcher(IndexReader reader) { return new IndexSearcher(reader); } /** * Lucene分页查询 * @param directoryPath * @param query * @param page * @throws IOException */ public static void pageQuery(String directoryPath,Query query,Page<Document> page) throws IOException { IndexSearcher searcher = createIndexSearcher(directoryPath); int totalRecord = searchTotalRecord(searcher,query); //设置总记录数 page.setTotalRecord(totalRecord); TopDocs topDocs = searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize()); List<Document> docList = new ArrayList<Document>(); ScoreDoc[] docs = topDocs.scoreDocs; int index = 0; for (ScoreDoc scoreDoc : docs) { int docID = scoreDoc.doc; Document document = searcher.doc(docID); if(index == docs.length - 1) { page.setAfterDoc(scoreDoc); page.setAfterDocId(docID); } docList.add(document); index++; } page.setItems(docList); searcher.getIndexReader().close(); } /** * 索引分页查询 * @param fieldName * @param queryString * @param currentPage * @param pageSize * @throws ParseException * @throws IOException */ public static Page<Document> pageQuery(String fieldName,String queryString,String directoryPath,int currentPage,int pageSize) throws ParseException, IOException { QueryParser parser = new QueryParser(fieldName, new StandardAnalyzer()); Query query = parser.parse(queryString); Page<Document> page = new Page<Document>(currentPage,pageSize); pageQuery(directoryPath, query, page); return page; } /** * @Title: searchTotalRecord * @Description: 获取符合条件的总记录数 * @param query * @return * @throws IOException */ public static int searchTotalRecord(IndexSearcher searcher,Query query) throws IOException { TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE); if(topDocs == null || topDocs.scoreDocs == null || topDocs.scoreDocs.length == 0) { return 0; } ScoreDoc[] docs = topDocs.scoreDocs; return docs.length; } }
其实查询的核心代码就这一句:
searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize());
searchAfter方法用于分页,如果不需要分页,请使用search方法。
searchAfter需要接收3个参数:
1.afterDocId即下一个Document的id,
2.query接口实现类的对象,query对象可以通过QueryParser类来创建,也可以自己new Query接口的某一个特定接口实现类,Query接口内置有N种实现,具体请查阅Lucene API,这里附上本人制作的Lucene5.0 API文档下载地址:http://pan.baidu.com/s/1uEgB8
3.pageSize即每页显示几条,你懂的。
至于如何创建IndexSearcher实例请看代码,跟Lucene4.x的使用方式没什么太大的区别,有一个较大的区别就是Lucene5.0里打开索引目录采用的是NIO2.0的方式,在Lucene4.0里你打开索引目录是这样的:
FSDirectory.open(directoryPath);
这里的directoryPath为String类型即你的索引目录,而在Lucene5.0里,则是使用NIO2.0的方式:
FSDirectory.open(Paths.get(directoryPath, new String[0]))
FSDirectory.open接收的参数不再是String类型而是Path类型。
测试类里关联了一个自己写的Page分页工具类,代码如下:
package com.yida.framework.lucene5.util; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.lucene.document.Document; import org.apache.lucene.search.ScoreDoc; public class Page<T> { /**当前第几页(从1开始计算)*/ private int currentPage; /**每页显示几条*/ private int pageSize; /**总记录数*/ private int totalRecord; /**总页数*/ private int totalPage; /**分页数据集合[用泛型T来限定集合元素类型]*/ private Collection<T> items; /**当前显示起始索引(从零开始计算)*/ private int startIndex; /**当前显示结束索引(从零开始计算)*/ private int endIndex; /**一组最多显示几个页码[比如Google一组最多显示10个页码]*/ private int groupSize; /**左边偏移量*/ private int leftOffset = 5; /**右边偏移量*/ private int rightOffset = 4; /**当前页码范围*/ private String[] pageRange; /**分页数据*/ private List<Document> docList; /**上一页最后一个ScoreDoc对象*/ private ScoreDoc afterDoc; /**上一页最后一个ScoreDoc对象的Document对象ID*/ private int afterDocId; public void setRangeIndex() { int groupSize = getGroupSize(); int totalPage = getTotalPage(); if(totalPage < 2) { startIndex = 0; endIndex = totalPage - startIndex; } else { int currentPage = getCurrentPage(); if(groupSize >= totalPage) { startIndex = 0; endIndex = totalPage - startIndex - 1; } else { int leftOffset = getLeftOffset(); int middleOffset = getMiddleOffset(); if(-1 == middleOffset) { startIndex = 0; endIndex = groupSize - 1; } else if(currentPage <= leftOffset) { startIndex = 0; endIndex = groupSize - 1; } else { startIndex = currentPage - leftOffset - 1; if(currentPage + rightOffset > totalPage) { endIndex = totalPage - 1; } else { endIndex = currentPage + rightOffset - 1; } } } } } public int getCurrentPage() { if(currentPage <= 0) { currentPage = 1; } else { int totalPage = getTotalPage(); if(totalPage > 0 && currentPage > getTotalPage()) { currentPage = totalPage; } } return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { if(pageSize <= 0) { pageSize = 10; } return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotalRecord() { return totalRecord; } public void setTotalRecord(int totalRecord) { this.totalRecord = totalRecord; } public int getTotalPage() { int totalRecord = getTotalRecord(); if(totalRecord == 0) { totalPage = 0; } else { int pageSize = getPageSize(); totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize : (totalRecord / pageSize) + 1; } return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public int getStartIndex() { return startIndex; } public void setStartIndex(int startIndex) { this.startIndex = startIndex; } public int getEndIndex() { return endIndex; } public void setEndIndex(int endIndex) { this.endIndex = endIndex; } public int getGroupSize() { if(groupSize <= 0) { groupSize = 10; } return groupSize; } public void setGroupSize(int groupSize) { this.groupSize = groupSize; } public int getLeftOffset() { leftOffset = getGroupSize() / 2; return leftOffset; } public void setLeftOffset(int leftOffset) { this.leftOffset = leftOffset; } public int getRightOffset() { int groupSize = getGroupSize(); if(groupSize % 2 == 0) { rightOffset = (groupSize / 2) - 1; } else { rightOffset = groupSize / 2; } return rightOffset; } public void setRightOffset(int rightOffset) { this.rightOffset = rightOffset; } /**中心位置索引[从1开始计算]*/ public int getMiddleOffset() { int groupSize = getGroupSize(); int totalPage = getTotalPage(); if(groupSize >= totalPage) { return -1; } return getLeftOffset() + 1; } public String[] getPageRange() { setRangeIndex(); int size = endIndex - startIndex + 1; if(size <= 0) { return new String[0]; } if(totalPage == 1) { return new String[] {"1"}; } pageRange = new String[size]; for(int i=0; i < size; i++) { pageRange[i] = (startIndex + i + 1) + ""; } return pageRange; } public void setPageRange(String[] pageRange) { this.pageRange = pageRange; } public Collection<T> getItems() { return items; } public void setItems(Collection<T> items) { this.items = items; } public List<Document> getDocList() { return docList; } public void setDocList(List<Document> docList) { this.docList = docList; } public ScoreDoc getAfterDoc() { setAfterDocId(afterDocId); return afterDoc; } public void setAfterDoc(ScoreDoc afterDoc) { this.afterDoc = afterDoc; } public int getAfterDocId() { return afterDocId; } public void setAfterDocId(int afterDocId) { this.afterDocId = afterDocId; if(null == afterDoc) { this.afterDoc = new ScoreDoc(afterDocId, 1.0f); } } public Page() {} public Page(int currentPage, int pageSize) { this.currentPage = currentPage; this.pageSize = pageSize; } public Page(int currentPage, int pageSize, Collection<T> items) { this.currentPage = currentPage; this.pageSize = pageSize; this.items = items; } public Page(int currentPage, int pageSize, Collection<T> items, int groupSize) { this.currentPage = currentPage; this.pageSize = pageSize; this.items = items; this.groupSize = groupSize; } public Page(int currentPage, int pageSize, int groupSize, int afterDocId) { this.currentPage = currentPage; this.pageSize = pageSize; this.groupSize = groupSize; this.afterDocId = afterDocId; } public static void main(String[] args) { Collection<Integer> items = new ArrayList<Integer>(); int totalRecord = 201; for(int i=0; i < totalRecord; i++) { items.add(new Integer(i)); } Page<Integer> page = new Page<Integer>(1,10,items,10); page.setTotalRecord(totalRecord); int totalPage = page.getTotalPage(); for(int i=0; i < totalPage; i++) { page.setCurrentPage(i+1); String[] pageRange = page.getPageRange(); System.out.println("当前第" + page.currentPage + "页"); for(int j=0; j < pageRange.length; j++) { System.out.print(pageRange[j] + " "); } System.out.println("\n"); } } }
来张运行效果图大家感受下:
demo源代码请在附件里下载,千言万语都在代码中,你们懂的。
若你还有什么疑问,请加我Q-Q:7-3-6-0-3-1-3-0-5,或者加裙:
,欢迎你加入一起交流学习。
相关推荐
这篇博客“Lucene5学习之自定义Collector”显然聚焦于如何在Lucene 5版本中通过自定义Collector来优化搜索结果的收集过程。Collector是Lucene搜索框架中的一个重要组件,它负责在搜索过程中收集匹配的文档,并根据...
本压缩包中的代码着重展示了如何使用 Lucene 进行分页搜索和结果高亮显示。下面将详细解释这两个关键知识点。 **一、Lucene 分页搜索** 在大型数据集上进行搜索时,一次性返回所有结果并不实际,因此分页搜索显得...
《Lucene学习实战系列:高亮与分页技术解析》 Lucene,作为Apache软件基金会的一个开源全文搜索引擎库,被广泛应用于各种搜索场景。本文将深入探讨如何在Lucene中实现高亮显示搜索结果和高效的分页功能,帮助开发者...
在"一步一步跟我学习lucene(12)---lucene搜索之分组处理group查询"中,我们将重点关注如何利用Lucene实现这一高级搜索功能。 首先,Lucene是一个开源全文搜索引擎库,它为Java开发者提供了构建高效、可扩展的搜索...
2. 代码示例:通过分析提供的"lucene4.8学习资料和案例"压缩包,可以深入了解Lucene的实践操作,如创建索引、执行查询、处理结果等。 3. 在线教程:网络上有许多优秀的Lucene教程,如《Lucene in Action》一书的在线...
5. **评分(Scoring)**:Lucene会根据查询和文档的相关性给出一个分数,决定搜索结果的排序。TF-IDF(Term Frequency-Inverse Document Frequency)是最常用的评分算法。 现在,我们详细讲解如何在Lucene中进行...
这是另一份全面的Lucene学习资料,可能涵盖了Lucene的主要特性和应用,包括分析器的使用、查询解析、索引优化等。 6. **新闻系统全文检索的思绪.txt** 这篇文章可能探讨了在新闻系统中集成全文检索的策略,包括...
以上是对 Lucene 3.5 的学习笔记总结,涵盖了从索引构建到查询操作的基础和高级功能。通过深入理解这些概念和实践应用,可以帮助开发者更好地利用 Lucene 和 Solr 构建高效且功能强大的搜索应用。
《深入探索Lucene 3.5:学习研究报告》 Lucene 3.5是一个重要的版本更新,它在2011年11月26日发布,为搜索引擎开发者提供了更高效、更稳定的功能。该版本在性能优化、新特性和错误修复上取得了显著的进步。 首先,...
标题 "我封装的搜索引擎之lucene篇" 暗示了这个压缩包文件包含与Lucene搜索引擎相关的代码或文档。Lucene是Apache软件基金会的开源全文检索库,它提供了高级的文本分析和索引功能,使得开发者能够轻松地在应用程序中...
**Lucene 概述** Lucene 是一个高性能、全文本搜索库...实际的 "luceneDemo" 可能包含更丰富的功能,例如支持多字段查询、高亮显示搜索结果、分页显示等。学习和理解 Lucene,可以帮助开发者构建强大的全文检索系统。
《Lucene 4.4 实战教程:从基础到进阶》 Lucene是一个高性能、全文本搜索引擎库,由Apache软件基金会开发。...这个Demo案例旨在引导你入门,希望你在学习Lucene的旅程中找到乐趣,不断提高你的搜索引擎开发能力。
5. **内存缓存与倒排索引优化**:Lucene提供缓存机制,如BitSet缓存,可以提高查询性能。同时,通过设置不同类型的Filter和FilterCache,可以进一步优化倒排索引的访问。 6. **实时搜索与更新**:Lucene支持实时...
【标题】"lucene学习03" 涉及到的是Apache Lucene,这是一个高性能、全文本搜索引擎库,广泛应用于各种信息检索系统。在Lucene的学习过程中,我们通常会涵盖以下几个核心知识点: 1. **Lucene简介**:Lucene是一个...
在IT领域,Lucene是一个非常...然而,Lucene的功能远不止于此,它还包括过滤、排序、分页、高亮显示、近似查询等高级特性。随着对这些基础类的深入理解和实践,你将逐步掌握Lucene的精髓,并能灵活应用到实际项目中。
5. **结果展示**:服务器将搜索结果返回给前端,前端通常会展示相关度最高的结果,并可能提供分页、排序等功能。 在`sample.dw.paper.lucene`这个压缩包中,很可能包含了示例代码,用于演示如何在实际项目中集成...
总之,"lucene检索小例子"是一个实用的教程,通过它你可以学习到如何利用Lucene这一强大的全文搜索引擎库,实现高效、精准的文本检索功能。无论是在网站、数据库还是其他任何需要搜索功能的应用中,Lucene都是一个...
查询时,需要创建查询对象,使用查询执行器在索引库中执行查询,获取搜索结果,并根据需要对结果进行排序和分页。 通过学习Lucene3.0 使用教程,开发者能够掌握全文检索的基本原理和技术,为自己的应用系统添加高效...
5. 查询处理:用户输入查询后,Lucene解析查询语句,生成查询计划并执行,返回匹配的文档。 **三、主要组件** 1. **Analyzer**:负责文本分析,包括分词、去除停用词等。 2. **Document**:代表要索引的数据,包含...