lucene 查询+分页+排序
lucene 查询+分页+排序
1、定义一个工厂类
LuceneFactory
1 import java.io.IOException;
2
3 import org.apache.lucene.analysis.Analyzer;
4 import org.apache.lucene.index.CorruptIndexException;
5 import org.apache.lucene.index.IndexReader;
6 import org.apache.lucene.index.IndexWriter;
7 import org.apache.lucene.index.IndexWriterConfig;
8 import org.apache.lucene.search.IndexSearcher;
9 import org.apache.lucene.store.Directory;
10 import org.apache.lucene.store.FSDirectory;
11 import org.apache.lucene.util.Version;
12 import org.wltea.analyzer.lucene.IKAnalyzer;
13
14 import cn.utils.Constant;
15
16 public class LuceneFactory
17 {
18 private static IndexReader fileReader = null;
19 private static Directory fileDirectory = null;
20 private static IndexWriter fileWriter = null;
21
22 public static Analyzer ana = new IKAnalyzer();
23
24
25
26 /**
27 * 获取indexwriter
28 * @return
29 * @throws IOException
30 */
31 public static synchronized IndexWriter getFileWrite() throws IOException
32 {
33
34 if(fileWriter == null){
35 fileDirectory = FSDirectory.open(Constant.file_index_path_File);
36 if (IndexWriter.isLocked(fileDirectory)) {
37 IndexWriter.unlock(fileDirectory);
38 }
39 fileWriter = new IndexWriter(fileDirectory, new IndexWriterConfig(Version.LUCENE_36, ana));
40
41 return fileWriter;
42 }
43
44 System.out.println("filewriter != null");
45
46 return fileWriter;
47 }
48
49 /**
50 *获得IndexReader对象,判断是否为最新,不是则重新打开
51 *@param file 索引路径的File对象
52 **/
53 public static synchronized IndexReader getFileRead() throws IOException
54 {
55 if (fileReader == null) {
56 fileDirectory = FSDirectory.open(Constant.file_index_path_File);
57 fileReader = IndexReader.open(fileDirectory);
58 } else {
59 if (!fileReader.isCurrent()) {
60 fileReader = IndexReader.openIfChanged(fileReader);
61 }
62 }
63
64 return fileReader;
65 }
66
67 /***
68 * 获得IndexSearcher对象,判断当前的Searcher中reader是否为最新,如果不是,则重新创建IndexSearcher
69 *
70 * @return
71 * @throws IOException
72 */
73 public static synchronized IndexSearcher getFileSearch() throws IOException
74 {
75 /*if (fileSearcher == null) {
76 fileDirectory = FSDirectory.open(file_index_path);
77 fileSearcher = new IndexSearcher(IndexReader.open(fileDirectory));
78 } else {
79 IndexReader r = fileSearcher.getIndexReader();
80 if (!r.isCurrent()) {
81 fileSearcher.close();
82 fileSearcher = new IndexSearcher(IndexReader.openIfChanged(r));
83 }
84 }
85
86 return fileSearcher;*/
87
88 return new IndexSearcher(getFileRead());
89 }
90
91 public static void closeFileWrite()
92 {
93 if(fileWriter != null)
94 {
95 try
96 {
97 fileWriter.commit();
98 fileWriter.close();
99 } catch (CorruptIndexException e)
100 {
101
102 e.printStackTrace();
103 } catch (IOException e)
104 {
105
106 e.printStackTrace();
107 }
108
109 }
110 }
111
112 }
2、定义返回结果bean
1 import java.util.List;
2
3 import org.apache.lucene.document.Document;
4
5 public class SearchResultBean
6 {
7 private int totalHits;
8 private List<Document> docs;
9
10 public SearchResultBean()
11 {
12
13 }
14
15 public SearchResultBean(int totalHits, List<Document> docs)
16 {
17 this.totalHits = totalHits;
18 this.docs = docs;
19 }
20
21 public int getTotalHits()
22 {
23 return this.totalHits;
24 }
25
26 public void setTotalHits(int totalHits)
27 {
28 this.totalHits = totalHits;
29 }
30
31 public List<Document> getDocs()
32 {
33 return this.docs;
34 }
35
36 public void setDocs(List<Document> docs)
37 {
38 this.docs = docs;
39 }
40 }
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、搜索方法 重点
1 /****
2 * 命名不是很好
3 * @param field:暂时么用
4 * @param query:query
5 * @param first:分页起始值,如第一页0, first 0 max 20,第二页 first20, max 20
6 * @param max:每页显示的数目,如20
7 * @param sort:排序
8 * @param highLight:是否高亮,这里不咱贴代码
9 * @return
10 */
11 public static SearchResultBean searchAndSort(String field, Query query, int first,
12 int max, Sort sort, boolean highLight)
13 {
14 if(query == null){
15 System.out.println(" Query is null return null ");
16 return null;
17 }
18 try
19 {
20 List<Document> docs = new ArrayList<Document>();
21 IndexSearcher searcher = LuceneFactory.getFileSearch();
22
23 TopFieldCollector c = TopFieldCollector.create(sort, first+max, false, false, false, false);
24 searcher.search(query, c);
25 ScoreDoc[] hits = c.topDocs(first, max).scoreDocs;
26 if (hits == null || hits.length < 1)
27 return null;
28
29 // 高亮------------------------------
30 Formatter htmlFormatter = null;
31 if (highLight)
32 htmlFormatter = new SimpleHTMLFormatter(
33 "<span style='color:red;'>", "</span>");
34 else
35 htmlFormatter = new SimpleHTMLFormatter("", "");
36
37 Scorer scorer = new QueryScorer(query);
38 //Encoder encoder = new SimpleHTMLEncoder();
39 Fragmenter fragmenter = new SimpleFragmenter(Max_Match_Num);
40 Highlighter highlighter = new Highlighter(htmlFormatter, scorer);
41 highlighter.setTextFragmenter(fragmenter);
42
43 for (int i = 0; i < hits.length; i++)
44 {
45 Document doc = searcher.doc(hits[i].doc);
46 highlight(highlighter, doc, field);
47
48 docs.add(doc);
49 }
50
51 return new SearchResultBean(c.getTotalHits(), docs);
52 } catch (Exception e)
53 {
54 return null;
55 }
56 }
57
- 第23行,max+first 值无所谓,返回的是命中数,不会是一个list集合,不用担心内存开销
- 第38行,中文分词、做高亮的时候,不注释这段代码,高亮的结果是unicode编码,搞不懂,暂时没研究。我用IK分词,测试与IK无关。
- 第51行,c.getTotalHits(),回到第一个问题,就是lucene分页,以前做数据库分页的时候,需要查询2次,而lucene只需要一次就OK。
分页jsp页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<%@ page language= "java" pageEncoding= "UTF-8" %> <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> |
lucene 查询+分页+排序的更多相关文章
- Lucene 查询分页技术
常用的Lucene查询代码如下所示,该代码的作用是将path路径下的所有索引信息返回 public String matchAll(String path) { try { Directory dir ...
- springboot整合Mangodb实现crud,高级查询,分页,排序,简单聚合
//linux安装mangodb教程:https://www.cnblogs.com/yangxiaohui227/p/11347832.html 1.引入maven 依赖 <dependenc ...
- 动态多条件查询分页以及排序(一)--MVC与Entity Framework版url分页版
一.前言 多条件查询分页以及排序 每个系统里都会有这个的代码 做好这块 可以大大提高开发效率 所以博主分享下自己的6个版本的 多条件查询分页以及排序 二.目前状况 不论是ado.net 还是EF ...
- 测试使用索引库crud和高级查询分页
1.搭建ES的服务 导入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifa ...
- 对于Oracle中分页排序查询语句执行效率的比较分析
转自:http://bbs.csdn.net/topics/370033478 对于Oracle中分页排序查询语句执行效率的比较分析 作者:lzgame 在工作中我们经常遇到需要在Oracle中进行分 ...
- Oracle 数据库分页查询与排序分页查询
一.分页查询 原始查询语句 SELECT * FROM NASLE_WFSHH 修改为分页查询语句,加上 ROWNUM 列.此处为查询第 1 页,每页 9 条数据 SELECT * FROM ( SE ...
- 在ASP.NET MVC中使用Boostrap实现产品的展示、查询、排序、分页
在产品展示中,通常涉及产品的展示方式.查询.排序.分页,本篇就在ASP.NET MVC下,使用Boostrap来实现. 源码放在了GitHub: https://github.com/darrenji ...
- JPA或Hibernate中使用原生SQL实现分页查询、排序
发生背景:前端展示的数据需要来自A表和D表拼接,A表和D表根据A表的主键进行关联,D表的非主键字段关联C表的主键,根据条件筛选出符合的数据,并且根据A表的主键关联B表的主键(多主键)的条件,过滤A表中 ...
- MySQL全面瓦解9:查询的排序、分页相关
概述 数据库中的数据直接呈现出来一般不是我们想要的,所以我们上两节演示了如何对数据进行过滤的方法.除了对数据进行过滤, 我们可能还需要对数据进行排序,比如想从列表中了解消费最高的项,就可能需要对金额字 ...
随机推荐
- Introducing Visual Studio’s Emulator for Android
visual studio 2015支持Android开发了. Microsoft released Visual Studio 2015 Preview this week and with it ...
- IplImage 封装释放
IplImage是openCV库中非常重要的一个结构体,库中的图像都是保存为这个结构体后再进行操作的,详细结构例如以下: </pre><pre> typedef struct ...
- 从源代码上分析ListView的addHeaderView和setAdapter的调用顺序
ListView想要加入headerview的话,就要通过addHeaderView这种方法,然后想要为ListView设置数据的话,就要调用setAdapter方法了.可是,在调用addHeader ...
- protobuf-net-data
protobuf-net http://www.codeproject.com/Articles/642677/Protobuf-net-the-unofficial-manual https://g ...
- How to:Installshield判断操作系统是否为64位,并且为操作注册表进行设置
原文:How to:Installshield判断操作系统是否为64位,并且为操作注册表进行设置 IS脚本操作注册表在64位平台下必须有特殊的设置 if (SYSINFO.bIsWow64) then ...
- POJ 1284 Primitive Roots 原根
题目来源:POJ 1284 Primitive Roots 题意:求奇素数的原根数 思路:一个数n是奇素数才有原根 原根数是n-1的欧拉函数 #include <cstdio> const ...
- MVC多模板支持
参考: ASP.NET MVC:多模板支持
- (64位oracle使用32位的PLSQL)安装64位的oracle数据库软件,使用32位的PLSQL Developer连接方法
因为PLSQL Developer没有提供64位的,于是依据网上的资料做了一下整理,发上来 1.下载并安装Oracle 11g R2 64位,在server上安装时忽略硬件检測失败信息: 2.下载Or ...
- LibVLC audio controls
原文 http://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc__audio.html LibVLC audio co ...
- 1001 - Another A+B
1001 - Another A+B Description Give you an integer a, you are to find two another integers which sum ...