lucene第一步---6.分页

本文介绍如何使用Lucene进行分页搜索,包括创建索引、实现分页类及分页查询方法。通过实例演示了如何针对特定内容进行查询,并展示查询结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

lucene第一步---6.分页
创建测试数据的索引

String path = "index";//索引目录
Analyzer analyzer = new IKAnalyzer();//采用的分词器
IndexWriter iwriter = new IndexWriter(path, analyzer, true);
File dir = new File("data");//
File[] files = dir.listFiles();
for(int i=0;i<files.length;i++){
Document doc = new Document();
File file = files[i];
System.out.println(file.getName());
System.out.println(file.getPath());
FileInputStream fis = new FileInputStream(file);
String content = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));

StringBuffer buffer = new StringBuffer("");
content = reader.readLine();
while (content != null) {
buffer.append(content);
content = reader.readLine();
}
System.out.println("content : "+buffer.toString());
doc.add(new Field("title",file.getName(),Field.Store.YES,Field.Index.ANALYZED));
doc.add(new Field("content",buffer.toString(),Field.Store.YES,Field.Index.ANALYZED));
iwriter.addDocument(doc);
}
iwriter.close();

我们创建分页类,没什么说的一个bean

import java.util.ArrayList;

import org.apache.lucene.document.Document;

public class Page{
private static int DEFAULT_PAGE_SIZE = 5;

private int pageSize = DEFAULT_PAGE_SIZE; // 每页的记录数

private long start; // 当前页第一条数据在数据集合中的位置,从0开始

private Object data; // 当前页中存放的记录,类型一般为List

private long totalCount; // 总记录数

public Page() {
this(0, 0, 5,new ArrayList<Document>());
}

public Page(long start, long totalCount, int pageSize, Object data) {
this.start = start;
this.totalCount = totalCount;
this.pageSize = pageSize;
this.data = data;
}

/**
* 取得总记录数
* @return
*/
public long getTotalCount() {
return this.totalCount;
}
/**
* 取当前页中的数据
* @return
*/
public Object getResult() {
return this.data;
}

/**
* 取每页的数据容量
* @return
*/
public int getPageSize() {
return this.pageSize;
}
/**
* 取总页数
* @return
*/
public long getTotalPageCount() {
return totalCount % pageSize == 0 ? totalCount / pageSize : totalCount
/ pageSize + 1;
}

/**
* 取当前的页号
* @return
*/
public long getCurrentPageNo(){
return start/pageSize+1;
}

/**
* 该页是否有下一页.
*/
public boolean hasNextPage() {
return this.getCurrentPageNo() < this.getTotalPageCount();
}

/**
* 该页是否有上一页.
*/
public boolean hasPreviousPage() {
return this.getCurrentPageNo() > 1;
}

/**
* 获取任一页第一条数据在数据集的位置,每页条数使用默认值.
*
* @see #getStartOfPage(int,int)
*/
protected static int getStartOfPage(int pageNo) {
return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE);
}

/**
* 获取任一页第一条数据在数据集的位置.
*
* @param pageNo 从1开始的页号
* @param pageSize 每页记录条数
* @return 该页第一条数据
*/
public static int getStartOfPage(int pageNo, int pageSize) {
return (pageNo - 1) * pageSize;
}
}


下面我们做一个分页方法并进行测试


public class PageSearcher {

@SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException {
String path = "index";//索引目录
Directory dir = FSDirectory.open(new File(path));
IndexSearcher searcher = new IndexSearcher(dir,true);
Term term = new Term("content","网友");
Query query = new TermQuery(term);
Page page = getPageQuery(3, 3, query, searcher);
System.out.println("当前页号 "+page.getCurrentPageNo());
System.out.println("存在上一页? " + page.hasPreviousPage());
System.out.println("存在下一页? " + page.hasNextPage());
System.out.println("每页的记录数 " + page.getPageSize());
System.out.println("总页数 " + page.getTotalPageCount());
System.out.println("总记录数 " + page.getTotalCount());
//显示页面内容

ArrayList<Document> docs = (ArrayList<Document>) page.getResult();
for(Document doc:docs){
System.out.println(doc.get("content"));
}


}
/**
* 获取当前页
* @param pageNo 页号 从1开始
* @param pageSize 每页显示的最多记录条数
* @param query Query
* @param searcher Searcher
* @return
*/
public static Page getPageQuery(int pageNo,int pageSize,Query query,Searcher searcher){
TopScoreDocCollector topCollector=null;
List<Document> result = new ArrayList<Document>();
try {
//得到查询结果的总记录数
topCollector = TopScoreDocCollector.create(searcher.maxDoc(), false);
searcher.search(query, topCollector);
//查询当页的记录
ScoreDoc [] docs = topCollector.topDocs((pageNo-1)*pageSize,pageSize).scoreDocs;
for(ScoreDoc scdoc : docs){
try {
result.add(searcher.doc(scdoc.doc));
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return new Page(Page.getStartOfPage(pageNo,pageSize),topCollector.getTotalHits(),pageSize,result);
} catch (IOException e1) {
e1.printStackTrace();
}

return new Page();
}
}

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、付费专栏及课程。

余额充值