Lucene5学习之分页查询

Java代码  Lucene5学习之分页查询
  1. package com.yida.framework.lucene5.core;  
  2.   
  3. import java.io.IOException;  
  4. import java.nio.file.Paths;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7.   
  8. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  9. import org.apache.lucene.document.Document;  
  10. import org.apache.lucene.index.DirectoryReader;  
  11. import org.apache.lucene.index.IndexReader;  
  12. import org.apache.lucene.queryparser.classic.ParseException;  
  13. import org.apache.lucene.queryparser.classic.QueryParser;  
  14. import org.apache.lucene.search.IndexSearcher;  
  15. import org.apache.lucene.search.Query;  
  16. import org.apache.lucene.search.ScoreDoc;  
  17. import org.apache.lucene.search.TopDocs;  
  18. import org.apache.lucene.store.FSDirectory;  
  19.   
  20. import com.yida.framework.lucene5.util.Page;  
  21.   
  22. /** 
  23.  * Lucene搜索第一个示例 
  24.  * @author Lanxiaowei 
  25.  * 
  26.  */  
  27. public class SearchFirstTest {  
  28.     public static void main(String[] args) throws ParseException, IOException {  
  29.         //参数定义  
  30.         String directoryPath = "D:/lucenedir";  
  31.         String fieldName = "contents";  
  32.         String queryString = "mount";  
  33.         int currentPage = 1;  
  34.         int pageSize = 10;  
  35.           
  36.         Page<Document> page = pageQuery(fieldName, queryString, directoryPath, currentPage, pageSize);  
  37.         if(page == null || page.getItems() == null || page.getItems().size() == 0) {  
  38.             System.out.println("No results found.");  
  39.             return;  
  40.         }  
  41.         for(Document doc : page.getItems()) {  
  42.             String path = doc.get("path");  
  43.             String content = doc.get("contents");  
  44.             System.out.println("path:" + path);  
  45.             System.out.println("contents:" + content);  
  46.         }  
  47.     }  
  48.     /** 
  49.      * 创建索引阅读器 
  50.      * @param directoryPath  索引目录 
  51.      * @return 
  52.      * @throws IOException   可能会抛出IO异常 
  53.      */  
  54.     public static IndexReader createIndexReader(String directoryPath) throws IOException {  
  55.         return DirectoryReader.open(FSDirectory.open(Paths.get(directoryPath, new String[0])));  
  56.     }  
  57.       
  58.     /** 
  59.      * 创建索引查询器 
  60.      * @param directoryPath   索引目录 
  61.      * @return 
  62.      * @throws IOException 
  63.      */  
  64.     public static IndexSearcher createIndexSearcher(String directoryPath) throws IOException {  
  65.         return new IndexSearcher(createIndexReader(directoryPath));  
  66.     }  
  67.       
  68.     /** 
  69.      * 创建索引查询器 
  70.      * @param reader 
  71.      * @return 
  72.      */  
  73.     public static IndexSearcher createIndexSearcher(IndexReader reader) {  
  74.         return new IndexSearcher(reader);  
  75.     }  
  76.       
  77.     /** 
  78.      * Lucene分页查询 
  79.      * @param directoryPath 
  80.      * @param query 
  81.      * @param page 
  82.      * @throws IOException 
  83.      */  
  84.     public static void pageQuery(String directoryPath,Query query,Page<Document> page) throws IOException {  
  85.         IndexSearcher searcher = createIndexSearcher(directoryPath);  
  86.         int totalRecord = searchTotalRecord(searcher,query);  
  87.         //设置总记录数  
  88.         page.setTotalRecord(totalRecord);  
  89.         TopDocs topDocs = searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize());  
  90.         List<Document> docList = new ArrayList<Document>();  
  91.         ScoreDoc[] docs = topDocs.scoreDocs;  
  92.         int index = 0;  
  93.         for (ScoreDoc scoreDoc : docs) {  
  94.             int docID = scoreDoc.doc;  
  95.             Document document = searcher.doc(docID);  
  96.             if(index == docs.length - 1) {  
  97.                 page.setAfterDoc(scoreDoc);  
  98.                 page.setAfterDocId(docID);  
  99.             }  
  100.             docList.add(document);  
  101.             index++;  
  102.         }  
  103.         page.setItems(docList);  
  104.         searcher.getIndexReader().close();  
  105.     }  
  106.       
  107.     /** 
  108.      * 索引分页查询 
  109.      * @param fieldName 
  110.      * @param queryString 
  111.      * @param currentPage 
  112.      * @param pageSize 
  113.      * @throws ParseException  
  114.      * @throws IOException  
  115.      */  
  116.     public static Page<Document> pageQuery(String fieldName,String queryString,String directoryPath,int currentPage,int pageSize) throws ParseException, IOException {  
  117.         QueryParser parser = new QueryParser(fieldName, new StandardAnalyzer());  
  118.         Query query = parser.parse(queryString);  
  119.         Page<Document> page = new Page<Document>(currentPage,pageSize);  
  120.         pageQuery(directoryPath, query, page);  
  121.         return page;  
  122.     }  
  123.       
  124.     /** 
  125.      * @Title: searchTotalRecord 
  126.      * @Description: 获取符合条件的总记录数 
  127.      * @param query 
  128.      * @return 
  129.      * @throws IOException 
  130.      */  
  131.     public static int searchTotalRecord(IndexSearcher searcher,Query query) throws IOException {  
  132.         TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);  
  133.         if(topDocs == null || topDocs.scoreDocs == null || topDocs.scoreDocs.length == 0) {  
  134.             return 0;  
  135.         }  
  136.         ScoreDoc[] docs = topDocs.scoreDocs;  
  137.         return docs.length;  
  138.     }  
  139. }  

 其实查询的核心代码就这一句:
    

Java代码  Lucene5学习之分页查询
  1. searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize());  

 searchAfter方法用于分页,如果不需要分页,请使用search方法。

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即每页显示几条,你懂的。

 

至于如何创建IndexSearcher实例请看代码,跟Lucene4.x的使用方式没什么太大的区别,有一个较大的区别就是Lucene5.0里打开索引目录采用的是NIO2.0的方式,在Lucene4.0里你打开索引目录是这样的:

Java代码  Lucene5学习之分页查询
  1. FSDirectory.open(directoryPath);   

 这里的directoryPath为String类型即你的索引目录,而在Lucene5.0里,则是使用NIO2.0的方式:

Java代码  Lucene5学习之分页查询
  1. FSDirectory.open(Paths.get(directoryPath, new String[0]))  

 FSDirectory.open接收的参数不再是String类型而是Path类型。

 

 测试类里关联了一个自己写的Page分页工具类,代码如下:

Java代码  Lucene5学习之分页查询
  1. package com.yida.framework.lucene5.util;  
  2. import java.util.ArrayList;  
  3. import java.util.Collection;  
  4. import java.util.List;  
  5.   
  6. import org.apache.lucene.document.Document;  
  7. import org.apache.lucene.search.ScoreDoc;  
  8. public class Page<T> {  
  9.     /**当前第几页(从1开始计算)*/  
  10.     private int currentPage;  
  11.     /**每页显示几条*/  
  12.     private int pageSize;  
  13.     /**总记录数*/  
  14.     private int totalRecord;  
  15.     /**总页数*/  
  16.     private int totalPage;  
  17.     /**分页数据集合[用泛型T来限定集合元素类型]*/  
  18.     private Collection<T> items;  
  19.     /**当前显示起始索引(从零开始计算)*/  
  20.     private int startIndex;  
  21.     /**当前显示结束索引(从零开始计算)*/  
  22.     private int endIndex;  
  23.     /**一组最多显示几个页码[比如Google一组最多显示10个页码]*/  
  24.     private int groupSize;  
  25.       
  26.     /**左边偏移量*/  
  27.     private int leftOffset = 5;  
  28.     /**右边偏移量*/  
  29.     private int rightOffset = 4;  
  30.     /**当前页码范围*/  
  31.     private String[] pageRange;  
  32.       
  33.     /**分页数据*/  
  34.     private List<Document> docList;  
  35.     /**上一页最后一个ScoreDoc对象*/  
  36.     private ScoreDoc afterDoc;  
  37.       
  38.     /**上一页最后一个ScoreDoc对象的Document对象ID*/  
  39.     private int afterDocId;  
  40.   
  41.     public void setRangeIndex() {  
  42.         int groupSize = getGroupSize();  
  43.         int totalPage = getTotalPage();  
  44.         if(totalPage < 2) {  
  45.             startIndex = 0;  
  46.             endIndex = totalPage - startIndex;  
  47.         } else {  
  48.             int currentPage = getCurrentPage();  
  49.             if(groupSize >= totalPage) {  
  50.                 startIndex = 0;  
  51.                 endIndex = totalPage - startIndex - 1;  
  52.             } else {  
  53.                 int leftOffset = getLeftOffset();  
  54.                 int middleOffset = getMiddleOffset();  
  55.                 if(-1 == middleOffset) {  
  56.                     startIndex = 0;  
  57.                     endIndex = groupSize - 1;  
  58.                 } else if(currentPage <= leftOffset) {  
  59.                     startIndex = 0;  
  60.                     endIndex = groupSize - 1;  
  61.                 } else {  
  62.                     startIndex = currentPage - leftOffset - 1;  
  63.                     if(currentPage + rightOffset > totalPage) {  
  64.                         endIndex = totalPage - 1;  
  65.                     } else {  
  66.                         endIndex = currentPage + rightOffset - 1;  
  67.                     }  
  68.                 }  
  69.             }  
  70.         }  
  71.     }  
  72.       
  73.     public int getCurrentPage() {  
  74.         if(currentPage <= 0) {  
  75.             currentPage = 1;  
  76.         } else {  
  77.             int totalPage = getTotalPage();  
  78.             if(totalPage > 0 && currentPage > getTotalPage()) {  
  79.                 currentPage = totalPage;  
  80.             }  
  81.         }  
  82.         return currentPage;  
  83.     }  
  84.     public void setCurrentPage(int currentPage) {  
  85.         this.currentPage = currentPage;  
  86.     }  
  87.     public int getPageSize() {  
  88.         if(pageSize <= 0) {  
  89.             pageSize = 10;  
  90.         }  
  91.         return pageSize;  
  92.     }  
  93.     public void setPageSize(int pageSize) {  
  94.         this.pageSize = pageSize;  
  95.     }  
  96.     public int getTotalRecord() {  
  97.         return totalRecord;  
  98.     }  
  99.     public void setTotalRecord(int totalRecord) {  
  100.         this.totalRecord = totalRecord;  
  101.     }  
  102.     public int getTotalPage() {  
  103.         int totalRecord = getTotalRecord();  
  104.         if(totalRecord == 0) {  
  105.             totalPage = 0;  
  106.         } else {  
  107.             int pageSize = getPageSize();  
  108.             totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize : (totalRecord / pageSize) + 1;  
  109.         }  
  110.         return totalPage;  
  111.     }  
  112.     public void setTotalPage(int totalPage) {  
  113.         this.totalPage = totalPage;  
  114.     }  
  115.       
  116.     public int getStartIndex() {  
  117.         return startIndex;  
  118.     }  
  119.     public void setStartIndex(int startIndex) {  
  120.         this.startIndex = startIndex;  
  121.     }  
  122.       
  123.     public int getEndIndex() {  
  124.         return endIndex;  
  125.     }  
  126.     public void setEndIndex(int endIndex) {  
  127.         this.endIndex = endIndex;  
  128.     }  
  129.     public int getGroupSize() {  
  130.         if(groupSize <= 0) {  
  131.             groupSize = 10;  
  132.         }  
  133.         return groupSize;  
  134.     }  
  135.     public void setGroupSize(int groupSize) {  
  136.         this.groupSize = groupSize;  
  137.     }  
  138.       
  139.     public int getLeftOffset() {  
  140.         leftOffset = getGroupSize() / 2;  
  141.         return leftOffset;  
  142.           
  143.     }  
  144.     public void setLeftOffset(int leftOffset) {  
  145.         this.leftOffset = leftOffset;  
  146.     }  
  147.     public int getRightOffset() {  
  148.         int groupSize = getGroupSize();  
  149.         if(groupSize % 2 == 0) {  
  150.             rightOffset = (groupSize / 2) - 1;  
  151.         } else {  
  152.             rightOffset = groupSize / 2;  
  153.         }  
  154.         return rightOffset;  
  155.     }  
  156.     public void setRightOffset(int rightOffset) {  
  157.         this.rightOffset = rightOffset;  
  158.     }  
  159.       
  160.     /**中心位置索引[从1开始计算]*/  
  161.     public int getMiddleOffset() {  
  162.         int groupSize = getGroupSize();  
  163.         int totalPage = getTotalPage();  
  164.         if(groupSize >= totalPage) {  
  165.             return -1;  
  166.         }  
  167.         return getLeftOffset() + 1;  
  168.     }  
  169.     public String[] getPageRange() {  
  170.         setRangeIndex();  
  171.         int size = endIndex - startIndex + 1;  
  172.         if(size <= 0) {  
  173.             return new String[0];  
  174.         }  
  175.         if(totalPage == 1) {  
  176.             return new String[] {"1"};  
  177.         }  
  178.         pageRange = new String[size];  
  179.         for(int i=0; i < size; i++) {  
  180.             pageRange[i] = (startIndex + i + 1) + "";  
  181.         }  
  182.         return pageRange;  
  183.     }  
  184.   
  185.     public void setPageRange(String[] pageRange) {  
  186.         this.pageRange = pageRange;  
  187.     }  
  188.   
  189.     public Collection<T> getItems() {  
  190.         return items;  
  191.     }  
  192.     public void setItems(Collection<T> items) {  
  193.         this.items = items;  
  194.     }  
  195.       
  196.     public List<Document> getDocList() {  
  197.         return docList;  
  198.     }  
  199.   
  200.     public void setDocList(List<Document> docList) {  
  201.         this.docList = docList;  
  202.     }  
  203.   
  204.     public ScoreDoc getAfterDoc() {  
  205.         setAfterDocId(afterDocId);  
  206.         return afterDoc;  
  207.     }  
  208.   
  209.     public void setAfterDoc(ScoreDoc afterDoc) {  
  210.         this.afterDoc = afterDoc;  
  211.     }  
  212.       
  213.     public int getAfterDocId() {  
  214.         return afterDocId;  
  215.     }  
  216.   
  217.     public void setAfterDocId(int afterDocId) {  
  218.         this.afterDocId = afterDocId;  
  219.         if(null == afterDoc) {  
  220.             this.afterDoc = new ScoreDoc(afterDocId, 1.0f);  
  221.         }  
  222.     }  
  223.       
  224.     public Page() {}  
  225.   
  226.     public Page(int currentPage, int pageSize) {  
  227.         this.currentPage = currentPage;  
  228.         this.pageSize = pageSize;  
  229.     }  
  230.   
  231.     public Page(int currentPage, int pageSize, Collection<T> items) {  
  232.         this.currentPage = currentPage;  
  233.         this.pageSize = pageSize;  
  234.         this.items = items;  
  235.     }  
  236.   
  237.     public Page(int currentPage, int pageSize, Collection<T> items, int groupSize) {  
  238.         this.currentPage = currentPage;  
  239.         this.pageSize = pageSize;  
  240.         this.items = items;  
  241.         this.groupSize = groupSize;  
  242.     }  
  243.   
  244.     public Page(int currentPage, int pageSize, int groupSize, int afterDocId) {  
  245.         this.currentPage = currentPage;  
  246.         this.pageSize = pageSize;  
  247.         this.groupSize = groupSize;  
  248.         this.afterDocId = afterDocId;  
  249.     }  
  250.   
  251.     public static void main(String[] args) {  
  252.         Collection<Integer> items = new ArrayList<Integer>();  
  253.         int totalRecord = 201;  
  254.         for(int i=0; i < totalRecord; i++) {  
  255.             items.add(new Integer(i));  
  256.         }  
  257.         Page<Integer> page = new Page<Integer>(1,10,items,10);  
  258.         page.setTotalRecord(totalRecord);  
  259.         int totalPage = page.getTotalPage();  
  260.         for(int i=0; i < totalPage; i++) {  
  261.             page.setCurrentPage(i+1);  
  262.             String[] pageRange = page.getPageRange();  
  263.             System.out.println("当前第" + page.currentPage + "页");  
  264.             for(int j=0; j < pageRange.length; j++) {  
  265.                 System.out.print(pageRange[j] + "  ");  
  266.             }  
  267.             System.out.println("\n");  
  268.         }     
  269.     }  
  270. }  

 

来张运行效果图大家感受下:

 
Lucene5学习之分页查询
 demo源代码请在附件里下载,千言万语都在代码中,你们懂的。

若你还有什么疑问,请加我Q-Q:7-3-6-0-3-1-3-0-5,或者加裙:

Lucene5学习之分页查询,欢迎你加入一起交流学习。

转载:http://iamyida.iteye.com/blog/2193345

上一篇:SpringMVC中log4J与AOP


下一篇:C++类和异常例子