`

创建lucence分页数据

阅读更多
上边我们已经建立了索引和创建了索引文件接下来我们想做的就是查询这些索引。
package com.think3c.lucene.index;

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;

public class IndexSearch {

	/**
	 * 创建索引阅读器
	 * 
	 * @param directoryPath
	 *            索引目录
	 * @return 索引阅读器
	 * @throws IOException
	 *             可能会抛出IO异常
	 */
	public static IndexReader createIndexReader(String directoryPath) throws IOException {
		/**
		 * 跟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类型。
		 */
		return DirectoryReader.open(FSDirectory.open(Paths.get(directoryPath)));
	}

	/**
	 * 创建索引查询器
	 * 
	 * @param reader
	 * @return
	 */
	public static IndexSearcher createIndexSearcher(IndexReader reader) {
		return new IndexSearcher(reader);
	}

	/**
	 * 通过索引目录找到对应的索引查询器
	 * 
	 * @param directoryPath
	 *            目录文件
	 * @return
	 */
	public static IndexSearcher createIndexSearcher(String directoryPath) throws IOException {
		return new IndexSearcher(createIndexReader(directoryPath));
	}

	/**
	 * 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);
		// searchAfter方法用于分页,如果不需要分页,请使用search方法。search(Query query, int n)
		/**
		 * 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即每页显示几条,你懂的。
		 */
		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 directoryPath
	 * @param currentPage
	 * @param pageSize
	 * @return
	 * @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; 
	}
	/**
	 * 获得符合条件的总数
	 * 
	 * @param searcher
	 * @param query
	 * @return
	 * @throws IOException
	 */
	private 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;
	}
}

添加自己对应的page对象。
package com.think3c.lucene.index;

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");
		}
	}
}


接下来我们测试一下
package com.think3c.lucene.index;

import java.io.IOException;

import org.apache.lucene.document.Document;
import org.apache.lucene.queryparser.classic.ParseException;
import org.junit.Test;

/**
 * lucene 5.3.1
 * http://janle.iteye.com/blog/2254370
 * @author Janle
 *
 */
public class SearchTest {

	@Test
	public void TestqueryPage(){
		//参数定义  
	    String indexPath = "你的索引路径";  
	    String fieldName = "contents";  
	    String queryString = "scripts";  
	    int currentPage = 1;  
	    int pageSize = 10;  
	    Page<Document> page;
		try {
			page = IndexSearch.pageQuery(fieldName, queryString, indexPath, currentPage, pageSize);
			if(page == null || page.getItems() == null || page.getItems().size() == 0) {  
		        System.out.println("没有搜到");  
		        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);  
		    } 
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}  
	    
	} 

}



直接运行测试就好


代码就不解释了,上边有注释。

分享到:
评论

相关推荐

    自己写的lucene分页高亮显示代码

    本压缩包中的代码着重展示了如何使用 Lucene 进行分页搜索和结果高亮显示。下面将详细解释这两个关键知识点。 **一、Lucene 分页搜索** 在大型数据集上进行搜索时,一次性返回所有结果并不实际,因此分页搜索显得...

    lucene查询工具类和IndexSearcher分页查询示例

    在本文中,我们将深入探讨如何使用Lucene查询工具类和`IndexSearcher`进行分页查询,这在处理大量数据时尤其有用。Lucene是一个强大的全文搜索引擎库,它提供了高效、可扩展的文本检索功能。在Java开发环境中,...

    Lucene.net建立索引,检索分页Demo

    Lucene 提供了强大的文本分析、索引创建、文档检索以及搜索结果排序等功能。在 .NET 平台上,Lucene.net 提供了与原生 Lucene 相同的强大功能,并且完全兼容 .NET Framework 和 .NET Core。 1. **文本分析(Text ...

    lucene第一步---6.分页

    1. 创建索引:使用`IndexWriter`类,对要搜索的数据进行索引。 2. 执行查询:通过`IndexSearcher`的`search`或`searchAfter`方法,结合`Query`对象来执行查询。 3. 处理分页:计算总页数,根据用户选择的页码调整`...

    SSH + Lucene + 分页 + 排序 + 高亮 模拟简单新闻网站搜索引擎--data

    - **索引构建**:Lucene首先对新闻内容进行分析,创建倒排索引,便于快速查找包含特定关键词的文档。 - **查询解析**:用户输入的查询字符串被解析为Query对象,匹配索引中的Term或Phrase。 - **搜索执行**:使用...

    lucene的排序过滤和分页.zip

    本资料主要探讨了Lucene中的排序、过滤和分页技术,这些都是构建高效、实用的信息检索系统的重要组成部分。 **排序(Sorting)** 排序是Lucene中的一项核心功能,允许我们根据文档的某个或多个字段来对搜索结果...

    使用Lucene4.7实现搜索功能,分页+高亮

    标题中的“使用Lucene4.7实现搜索功能,分页+高亮”表明我们要讨论的是如何利用Apache Lucene 4.7版本来构建一个具备搜索、分页和高亮显示功能的系统。Lucene是一个高性能、全文本搜索引擎库,它提供了强大的文本...

    lucene 学习实战系列(高亮+分页)

    分页是处理大量数据时必不可少的功能,它允许用户按需加载和浏览结果。在Lucene中,分页主要通过控制搜索的起始位置(offset)和每页数量(limit)来实现。 2. 实现策略 - ScoreDoc排序:基于ScoreDoc对象的doc和...

    lucene全局搜索所需jar包

    - 实现全局搜索,需要将所有待搜索的数据都导入到 Lucene 的索引中,然后通过 QueryParser 创建查询,使用 Searcher 搜索索引。 3. **分页**: - 在大量搜索结果中,分页是必不可少的用户体验优化。Lucene 支持...

    Lucene.Net的DLL

    1. **创建索引**:首先,需要将要搜索的数据转换为Lucene.Net的Document对象,并使用IndexWriter写入索引。 2. **配置分析器**:根据需求选择或定制适合的分析器,对输入文本进行预处理。 3. **构建查询**:利用...

    luceneDemo

    **Lucene 概述** Lucene 是一个高性能、全文本搜索库...实际的 "luceneDemo" 可能包含更丰富的功能,例如支持多字段查询、高亮显示搜索结果、分页显示等。学习和理解 Lucene,可以帮助开发者构建强大的全文检索系统。

    lucene实现企业搜索实例

    创建索引是Lucene的第一步,这涉及到对文档数据的读取、分析和存储。你需要定义一个`Document`对象,然后添加各种字段,如`Field("title", "文档标题")`,`Field("content", "文档内容")`等。接着,使用`IndexWriter...

    lucene学习资料

    4. **lucene分页.txt** 分页在大型数据集的搜索中非常重要。这份文档可能讲解了如何在Lucene中实现搜索结果的分页显示,包括设置查询范围、控制返回结果的数量等技巧。 5. **Lucene 的学习 .txt** 这是另一份全面...

    lucene实现企业产品检索

    Lucene的核心是建立索引,将原始文本数据转化为结构化的、便于查询的数据结构。这个过程包括文本分析(Tokenization)、词干提取(Stemming)、去停用词(Stopword Removal)等步骤。在这个例子中,我们采用庖丁解牛...

    lucene4.4 Demo事例

    - **索引**: Lucene首先需要创建索引,将文本数据转换为可搜索的结构。索引过程包括分析、分词和倒排索引等步骤。 - **分析器**: 分析器负责将输入文本拆分成有意义的单位,即术语(tokens),并进行规范化,如...

    lucene检索小例子

    Lucene的核心特性包括文本分析、索引创建、查询解析以及高效的搜索算法,使得开发者能够轻松地在大量文本数据中实现快速、准确的搜索。 **1. 文本分析** Lucene的文本分析是其处理文本的关键步骤。它涉及将输入的...

    Lucene分词与查询详解

    3. **索引(Indexing)**:索引是Lucene的核心功能之一,它将文本数据转化为可供快速检索的结构。索引过程涉及构建倒排索引(Inverted Index),其中每个词元都指向包含该词元的文档列表。 4. **查询处理(Query ...

    LUCENE的搜索引擎例子

    1. **索引创建**:这是搜索引擎的第一步,我们需要遍历要索引的数据源(例如文件系统、数据库等),读取内容,并使用Lucene的Analyzer进行分词,然后创建Term(词项)和Document(文档)。Analyzer是负责文本分析的...

    Lucene3.0 使 用 教 程

    在实践中,开发者需要学习如何使用Lucene API来创建索引,包括读取数据源、实例化文档对象、定义字段和分析器,然后使用索引writer将文档添加到索引库。查询时,需要创建查询对象,使用查询执行器在索引库中执行查询...

    基于Lucene的中型搜索引擎(C#)

    - **建立索引**:将处理后的文本数据转换为Lucene的倒排索引,用于快速查找。 - **查询处理**:解析用户输入的查询,生成相应的查询对象。 - **搜索执行**:使用查询对象在索引中查找匹配的文档,计算相关性评分。 -...

Global site tag (gtag.js) - Google Analytics