lucene 查询+分页+排序

来源:互联网 发布:linux命令是什么 编辑:程序博客网 时间:2024/05/17 08:54

1、定义一个工厂类

LuceneFactory

  import java.io.IOException;    import org.apache.lucene.analysis.Analyzer;   import org.apache.lucene.index.CorruptIndexException;   import org.apache.lucene.index.IndexReader;   import org.apache.lucene.index.IndexWriter;   import org.apache.lucene.index.IndexWriterConfig;   import org.apache.lucene.search.IndexSearcher;  import org.apache.lucene.store.Directory;  import org.apache.lucene.store.FSDirectory;  import org.apache.lucene.util.Version; import org.wltea.analyzer.lucene.IKAnalyzer;    import cn.utils.Constant;    public class LuceneFactory  {      private static IndexReader fileReader = null;      private static Directory fileDirectory = null;      private static IndexWriter fileWriter = null;            public static Analyzer ana = new IKAnalyzer();                        /**       * 获取indexwriter       * @return       * @throws IOException       */      public static synchronized IndexWriter getFileWrite()  throws IOException       {                if(fileWriter == null){              fileDirectory = FSDirectory.open(Constant.file_index_path_File);              if (IndexWriter.isLocked(fileDirectory)) {                  IndexWriter.unlock(fileDirectory);              }             fileWriter = new IndexWriter(fileDirectory, new IndexWriterConfig(Version.LUCENE_36, ana));                            return fileWriter;          }                        System.out.println("filewriter != null");                    return fileWriter;      }            /**       *获得IndexReader对象,判断是否为最新,不是则重新打开       *@param file 索引路径的File对象       **/      public static synchronized IndexReader getFileRead() throws IOException       {          if (fileReader == null) {              fileDirectory = FSDirectory.open(Constant.file_index_path_File);              fileReader = IndexReader.open(fileDirectory);          } else {              if (!fileReader.isCurrent()) {                  fileReader = IndexReader.openIfChanged(fileReader);              }          }                    return fileReader;      }            /***       * 获得IndexSearcher对象,判断当前的Searcher中reader是否为最新,如果不是,则重新创建IndexSearcher       *        * @return       * @throws IOException       */      public static synchronized IndexSearcher getFileSearch() throws IOException       {          /*if (fileSearcher == null) {              fileDirectory = FSDirectory.open(file_index_path);             fileSearcher = new IndexSearcher(IndexReader.open(fileDirectory));         } else {             IndexReader r = fileSearcher.getIndexReader();             if (!r.isCurrent()) {                 fileSearcher.close();                 fileSearcher = new IndexSearcher(IndexReader.openIfChanged(r));             }         }                  return fileSearcher;*/                  return new IndexSearcher(getFileRead());     }          public static void closeFileWrite()     {         if(fileWriter != null)         {             try             {                 fileWriter.commit();                 fileWriter.close();             } catch (CorruptIndexException e)             {                                  e.printStackTrace();             } catch (IOException e)             {                                 e.printStackTrace();             }                      }     }      }

2、定义返回结果bean

  import java.util.List;    import org.apache.lucene.document.Document;    public class SearchResultBean  {      private int totalHits;      private List<Document> docs;       public SearchResultBean()     {              }      public SearchResultBean(int totalHits, List<Document> docs)     {         this.totalHits = totalHits;         this.docs = docs;     }     public int getTotalHits()     {         return this.totalHits;     }      public void setTotalHits(int totalHits)     {         this.totalHits = totalHits;     }      public List<Document> getDocs()     {         return this.docs;     }      public void setDocs(List<Document> docs)     {         this.docs = docs;     } }

3、分页bean

import java.util.ArrayList;import java.util.List;public class PageBean{    private int currentPage = 1;// 当前页数    private int totalPages = 0;// 总页数    private int pageSize = 0;// 每页显示数    private int totalRows = 0;// 总数据数    private int startNum = 0;// 开始记录    private int nextPage = 0;// 下一页    private int previousPage = 0;// 上一页    private boolean hasNextPage = false;// 是否有下一页    private boolean hasPreviousPage = false;// 是否有前一页    private List<String> pageCodes;    private int showPageSize = 8; //显示多少个超链接页面        public PageBean() {}    public PageBean(int pageSize, int currentPage, int totalRows)    {        this.pageSize = pageSize;        this.currentPage = currentPage;        this.totalRows = totalRows;        if ((totalRows % pageSize) == 0)        {            totalPages = totalRows / pageSize;        } else        {            totalPages = totalRows / pageSize + 1;        }        if (currentPage >= totalPages)        {            hasNextPage = false;            currentPage = totalPages;        } else        {            hasNextPage = true;        }        if (currentPage <= 1)        {            hasPreviousPage = false;            currentPage = 1;        } else        {            hasPreviousPage = true;        }        startNum = (currentPage - 1) * pageSize;        nextPage = currentPage + 1;        if (nextPage >= totalPages)        {            nextPage = totalPages;        }        previousPage = currentPage - 1;        if (previousPage <= 1)        {            previousPage = 1;        }        reflashPageCode();    }        public void reflashPageCode()    {        this.pageCodes = new ArrayList<String>();        if (this.totalPages <= this.showPageSize)        {            for (int i = 1; i <= this.totalPages; i++)            {                this.pageCodes.add(String.valueOf(i));            }            return;        }        int middleSide = this.showPageSize >> 1;        if (this.currentPage <= middleSide)        {            for (int i = 1; i <= this.showPageSize; i++)            {                this.pageCodes.add(String.valueOf(i));            }            this.pageCodes.add(String.valueOf(".."));            return;        }        if ((this.totalPages - this.currentPage) <= middleSide)        {            this.pageCodes.add(String.valueOf(".."));            for (int i = this.showPageSize - 1; i >= 0; i--)            {                this.pageCodes.add(String.valueOf(this.totalPages - i));            }            return;        }        if (middleSide < this.currentPage                && this.currentPage - (middleSide + 1) > 0)            this.pageCodes.add(String.valueOf(".."));        for (int i = 0; i < this.showPageSize; i++)        {            this.pageCodes.add(String.valueOf((this.currentPage + i)                    - middleSide));        }        if (middleSide > this.currentPage                || this.totalPages - (this.currentPage + middleSide) > 0)            this.pageCodes.add(String.valueOf(".."));    }    public boolean isHasNextPage()    {        return hasNextPage;    }    public boolean isHasPreviousPage()    {        return hasPreviousPage;    }    /**     * @return the nextPage     */    public int getNextPage()    {        return nextPage;    }    /**     * @param nextPage     *            the nextPage to set     */    public void setNextPage(int nextPage)    {        this.nextPage = nextPage;    }    /**     * @return the previousPage     */    public int getPreviousPage()    {        return previousPage;    }    /**     * @param previousPage     *            the previousPage to set     */    public void setPreviousPage(int previousPage)    {        this.previousPage = previousPage;    }    /**     * @return the currentPage     */    public int getCurrentPage()    {        return currentPage;    }    /**     * @param currentPage     *            the currentPage to set     */    public void setCurrentPage(int currentPage)    {        this.currentPage = currentPage;    }    /**     * @return the pageSize     */    public int getPageSize()    {        return pageSize;    }    /**     * @param pageSize     *            the pageSize to set     */    public void setPageSize(int pageSize)    {        this.pageSize = pageSize;    }    /**     * @return the totalPages     */    public int getTotalPages()    {        return totalPages;    }    /**     * @param totalPages     *            the totalPages to set     */    public void setTotalPages(int totalPages)    {        this.totalPages = totalPages;    }    /**     * @return the totalRows     */    public int getTotalRows()    {        return totalRows;    }    /**     * @param totalRows     *            the totalRows to set     */    public void setTotalRows(int totalRows)    {        this.totalRows = totalRows;    }    /**     * @param hasNextPage     *            the hasNextPage to set     */    public void setHasNextPage(boolean hasNextPage)    {        this.hasNextPage = hasNextPage;    }    /**     * @param hasPreviousPage     *            the hasPreviousPage to set     */    public void setHasPreviousPage(boolean hasPreviousPage)    {        this.hasPreviousPage = hasPreviousPage;    }    /**     * @return the startNum     */    public int getStartNum()    {        return startNum;    }    /**     * @param startNum     *            the startNum to set     */    public void setStartNum(int startNum)    {        this.startNum = startNum;    }    public List<String> getPageCodes()    {        if (this.pageCodes == null) {              return new ArrayList<String>();            }        return pageCodes;    }    public void setPageCodes(List<String> pageCodes)    {        this.pageCodes = pageCodes;    }    public int getShowPageSize()    {        return showPageSize;    }    public void setShowPageSize(int showPageSize)    {        this.showPageSize = showPageSize;    }    }

4、搜索方法 重点

  /****       * 命名不是很好       * @param field:暂时么用       * @param query:query       * @param first:分页起始值,如第一页0, first 0 max 20,第二页 first20, max 20       * @param max:每页显示的数目,如20       * @param sort:排序       * @param highLight:是否高亮,这里不咱贴代码      * @return      */     public static SearchResultBean searchAndSort(String field, Query query, int first,             int max, Sort sort, boolean highLight)     {         if(query == null){             System.out.println(" Query is null return null ");             return null;         }         try         {             List<Document> docs = new ArrayList<Document>();             IndexSearcher searcher = LuceneFactory.getFileSearch();              TopFieldCollector c = TopFieldCollector.create(sort, first+max, false, false, false, false);             searcher.search(query, c);             ScoreDoc[] hits = c.topDocs(first, max).scoreDocs;             if (hits == null || hits.length < 1)                 return null;              // 高亮------------------------------             Formatter htmlFormatter = null;             if (highLight)                 htmlFormatter = new SimpleHTMLFormatter(                         "<span style='color:red;'>", "</span>");             else                 htmlFormatter = new SimpleHTMLFormatter("", "");              Scorer scorer = new QueryScorer(query);             //Encoder encoder = new SimpleHTMLEncoder();             Fragmenter fragmenter = new SimpleFragmenter(Max_Match_Num);             Highlighter highlighter = new Highlighter(htmlFormatter, scorer);             highlighter.setTextFragmenter(fragmenter);              for (int i = 0; i < hits.length; i++)             {                 Document doc = searcher.doc(hits[i].doc);                 highlight(highlighter, doc, field);                  docs.add(doc);             }              return new SearchResultBean(c.getTotalHits(), docs);         } catch (Exception e)         {             return null;         }     }
  1.  第23行,max+first 值无所谓,返回的是命中数,不会是一个list集合,不用担心内存开销
  2.  第38行,中文分词、做高亮的时候,不注释这段代码,高亮的结果是unicode编码,搞不懂,暂时没研究。我用IK分词,测试与IK无关。
  3.  第51行, c.getTotalHits(),回到第一个问题,就是lucene分页,以前做数据库分页的时候,需要查询2次,而lucene只需要一次就OK。

分页jsp页面

<%@ page language="java" pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%><script type="text/javascript" src="${pageContext.request.contextPath}/script/jquery.js"></script><div class="pagelistbox">  <input type="hidden" name="currentPage" id="currentPage" value="${pager.currentPage}" />  <span>共 ${pager.totalPages} 页/${pager.totalRows}条记录 </span>  <c:if test="${pager.hasPreviousPage}">    <span class="indexPage"> <a href="${pageContext.request.contextPath}/${page_url}1">首页</a></span>  </c:if>  <c:forEach var="every" items="${pager.pageCodes}">    <c:choose>      <c:when test="${every ne fn:trim(pager.currentPage) && every eq '..'}">        <span>${every} </span>      </c:when>      <c:when test="${every ne fn:trim(pager.currentPage)}">        <a href="${pageContext.request.contextPath}/${page_url}${every}">${every}</a>      </c:when>      <c:otherwise>        <strong>${every}</strong>      </c:otherwise>    </c:choose>  </c:forEach>  <c:if test="${pager.hasNextPage}">    <a class="nextPage" href="${pageContext.request.contextPath}/${page_url}${pager.nextPage}">下页</a>    <a class="nextPage" href="${pageContext.request.contextPath}/${page_url}${pager.totalPages}">末页</a>  </c:if></div>
0 0
原创粉丝点击