分頁查詢只需傳入每頁顯示記錄數和當前頁就可以實現分頁查詢功能
Lucene分頁查詢是對搜索返回的結果進行分頁,而不是對搜索結果的總數量進行分頁,因此我們搜索的時候都是返回前n條記錄
package cn.mylucene;
import java.io.IOException;
import java.nio.file.Paths;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.queryparser.classic.QueryParser.Operator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.SearcherFactory;
import org.apache.lucene.search.SearcherManager;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.SortField.Type;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
public class SearchIndex {
public static void main(String[] args) throws IOException, ParseException {
String queryString="title:\"國\"";
Analyzer analyzer = new StandardAnalyzer(); //StandardAnalyzer:漢字一個一個字拆分索引
IndexSearcher is = getIndexSearcher();
QueryParser parser=new QueryParser("", analyzer);
parser.setDefaultOperator(Operator.AND);//默認狀態下,空格被認為是OR的關系,設置為空格為AND
Query query = parser.parse(queryString);
//排序
Sort sort = new Sort(new SortField("dt", Type.LONG, true));
TopDocs topDocs = is.search(query, 20,sort);
System.out.println("總共匹配多少個:" + topDocs.totalHits);
//獲取查詢結果集
ScoreDoc[] hits = topDocs.scoreDocs;
int pageSize=5;//每頁顯示記錄數
int curPage=2;//當前頁
//查詢起始記錄位置
int begin = pageSize * (curPage - 1);
//查詢終止記錄位置
int end = Math.min(begin + pageSize, hits.length);
//遍歷結果集
for(int i=begin;i<end;i++) {
int docID = hits[i].doc;
Document document = is.doc(docID);
System.out.println(document.get("id")+"-"+document.get("name")+"-"+document.get("dt")+"-"+document.get("title"));
}
closeIndexSearcher(is);
}
/*
* 解決:實現實時搜索功能
* 解決:在讀取索引文件內容時,索引文件的打開操作IndexSearcher是個非常耗時耗資源的操作
* */
private static byte[] synchronized_r = new byte[0];
private static SearcherManager searcherManager = null;
private static IndexSearcher getIndexSearcher() throws IOException {
IndexSearcher indexSearcher = null;
//保證在同一時刻最多只有一個線程執行該段代碼
synchronized (synchronized_r) {
if(searcherManager == null) {
searcherManager = new SearcherManager(FSDirectory.open(Paths.get("E:\\LuceneIndex")), new SearcherFactory());
}
/*
* 這個方法同DirectoryReader.openIfChanged(dirReader)效果一樣,其實底層還是調用的該方法實現的
* DirectoryReader.openIfChanged(dirReader)可以判斷當前Reader對象的索引有沒有被修改過
* 如果索引文件被更新過則重新加載該索引目錄
* 但是這個時候的重新加載則比單純的open(indexPath)要高效很多
* 它只是重新加載被更新過的文檔,而單純的open則是加載全部的文檔
* */
searcherManager.maybeRefresh();
//借用一個IndexSearcher對象的引用,記住該對象用完之后要歸還的,有借有還再借不難
indexSearcher = searcherManager.acquire();
}
return indexSearcher;
}
private static void closeIndexSearcher(IndexSearcher indexSearcher) throws IOException {
if(indexSearcher != null) {
searcherManager.release(indexSearcher);//歸還從SearcherManager處借來的IndexSearcher對象
}
indexSearcher = null;
}
}
