创建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();
}

}

}



直接运行测试就好


代码就不解释了,上边有注释。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在lucene搜索分页过程中,可以有两种方式 一种是将搜索结果集直接放到session中,但是假如结果集非常大,同时又存在大并发访问的时候,很可能造成服务器的内存不足,而使服务器宕机 还有一种是每次都重新进行搜索,这样虽然避免了内存溢出的可能,但是,每次搜索都要进行一次IO操作,如果大并发访问的时候,你要保证你的硬盘的转速足够的快,还要保证你的cpu有足够高的频率 而我们可以将这两种方式结合下,每次查询都多缓存一部分的结果集,翻页的时候看看所查询的内容是不是在已经存在在缓存当中,如果已经存在了就直接拿出来,如果不存在,就进行查询后,从缓存中读出来. 比如:现在我们有一个搜索结果集 一个有100条数据,每页显示10条,就有10页数据. 安装第一种的思路就是,我直接把这100条数据缓存起来,每次翻页时从缓存种读取 而第二种思路就是,我直接从搜索到的结果集种显示前十条给第一页显示,第二页的时候,我在查询一次,给出10-20条数据给第二页显示,我每次翻页都要重新查询 第三种思路就变成了 我第一页仅需要10条数据,但是我一次读出来50条数据,把这50条数据放入到缓存当中,当我需要10--20之间的数据的时候,我的发现我的这些数据已经在我的缓存种存在了,我就直接存缓存中把数据读出来,少了一次查询,速度自然也提高了很多. 如果我访问第六页的数据,我就把我的缓存更新一次.这样连续翻页10次才进行两次IO操作 同时又保证了内存不容易被溢出.而具体缓存设置多少,要看你的服务器的能力和访问的人数来决定

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值