上边我们已经建立了索引和创建了索引文件接下来我们想做的就是查询这些索引。
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();
}
}
}
直接运行测试就好
代码就不解释了,上边有注释。