solr工具类
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import base.Page;
import base.util.ConfigUtil;
import demo.bean.Article;
public class SolrService {
private static Logger log = Logger.getLogger(SolrService.class);
private static HttpSolrServer solrServer;
static {
solrServer = new HttpSolrServer(ConfigUtil.getValue("solr.url"));
solrServer.setConnectionTimeout(5000);
}
/**
* 分页查询,包含查询,分页,高亮及获取高亮处摘要等内容;不同于数据库的查询分页,
* solr的查询返回值中有文档总数,所以无需再次查询总条数。
*
* @param page 自定义的翻页对象,包含查询信息及当前页数据列表。
*/
public static void getByPage(Page page) {
SolrQuery query = new SolrQuery();
// 为防止和其他变量重名,在变量的开始加上condition的首字母c
String ckw = page.getConditions().get("kw").toString();
String cCatalogId = page.getConditions().get("catalogId").toString();
//查询指定分类中,指定的关键字
query.setQuery(ckw + " AND catalog_id:"+cCatalogId);
//按照时间排序
query.addSort("create_time", SolrQuery.ORDER.desc);
//开始页
query.setStart((int)page.getStart());
//一页显示多少条
query.setRows(page.getSize());
//设置高亮
query.setHighlight(true);// 开启高亮组件
query.addHighlightField("title");// 高亮字段
query.addHighlightField("content");// 高亮字段
//标记,高亮关键字前缀
query.setHighlightSimplePre("<font color='red'>");
query.setHighlightSimplePost("</font>");//后缀
/**
//获取高亮分片数,一般搜索词可能分布在文章中的不同位置,其所在一定长度的
语句即为一个片段,默认为1,但根据业务需要有时候需要多取出几个分片。
- 此处设置决定下文中titleList, contentList中元素的个数
**/
query.setHighlight(true).setHighlightSnippets(1);
/**
每个分片的最大长度,默认为100。
适当设置此值,如果太小,高亮的标题可能会显不全;
设置太大,摘要可能会太长。
**/
query.setHighlightFragsize(150);
List<Object> articles = new ArrayList<Object>();
try {
QueryResponse rsp = solrServer.query(query);
SolrDocumentList docs = rsp.getResults();
//获取所有高亮的字段
Map<String,Map<String,List<String>>> highlightMap=rsp.getHighlighting();
Iterator<SolrDocument> iter = docs.iterator();
while (iter.hasNext()) {
SolrDocument doc = iter.next();
String idStr = doc.getFieldValue("id").toString();
int id = Integer.parseInt(idStr);
String title = doc.getFieldValue("title").toString();
String description = doc.getFieldValue("description").toString();
String writer = doc.getFieldValue("writer").toString();
int catalogId = Integer.parseInt(doc.getFieldValue("catalog_id").toString());
Date createTime = (Date)doc.getFieldValue("create_time");
Article article = new Article();
article.setId(id);
article.setTitle(title);
article.setDescription(description);
article.setWriter(writer);
article.setCatalogId(catalogId);
article.setCreateTime(createTime);
List<String> titleList=highlightMap.get(idStr).get("title");
List<String> contentList=highlightMap.get(idStr).get("content");
//获取并设置高亮的字段title
if(titleList!=null && titleList.size()>0){
article.setTitle(titleList.get(0));
}
//获取并设置高亮的字段content
if(contentList!=null && contentList.size()>0){
article.setDescription(contentList.get(0));
}
articles.add(article);
}
page.setDatas(articles);
page.setCount(docs.getNumFound());
} catch (Exception e) {
log.error("从solr根据Page查询分页文档时遇到错误", e);
}
}
}
Page是自定义的翻页对象,包含查询条件和查询结果等变量
import java.util.List;
import java.util.Map;
/**
* 基类page中包含公有翻页参数及保存查询到的结果以被页面遍历,
* 被子类继承后将增加不同的查询条件 。
*
* @author David
*
*/
public class Page {
/** 每页显示条数默认为30条 */
public static final int DEFAULT_SIZE = 30;
/** 当前页码, 从1开始计 */
private int current;
/** 每页条数 */
private int size;
/** 总条数 */
private long count;
/** 查询参数 */
private Map<String, Object> conditions;
/** 当前页数据 */
private List<Object> datas;
public Page() {
// 设置默认值
current = 1;
size = DEFAULT_SIZE;
}
/** 获取当前页码 */
public int getCurrent() {
return current;
}
/** 设置当前页码 */
public void setCurrent(int current) {
this.current = current;
}
/** 获取每页显示条数 */
public int getSize() {
return size;
}
/** 设置每页显示条数 */
public void setSize(int size) {
this.size = size;
}
/** 获取查询参数 */
public Map<String, Object> getConditions() {
return conditions;
}
/** 设置查询参数 */
public void setConditions(Map<String, Object> conditions) {
this.conditions = conditions;
}
/** 获取当前页数据 */
public List<Object> getDatas() {
return datas;
}
/** 设置当前页数据 */
public void setDatas(List<Object> datas) {
this.datas = datas;
}
/** 获取总条数 */
public long getCount() {
return count;
}
/** 设置总条数 */
public void setCount(long count) {
this.count = count;
}
/** 获取总页数 */
public long getTotalPages() {
if (datas == null || datas.isEmpty())
return 0;
long totalPages = count / size;
if (count%size != 0) {
totalPages ++;
}
return totalPages;
}
/** 获取从第几条数据开始查询 */
public long getStart() {
return (current-1) * size;
}
/** 判断是否还有前一页 */
public boolean getHasPrevious() {
return current == 1 ? false : true;
}
/** 判断是否还有后一页 */
public boolean getHasNext() {
return (getTotalPages()!=0 && getTotalPages()!=current) ? true : false;
}
}
@Test
public void getByPage() {
Page page = new Page();
Map<String, Object> conditions = new HashMap<String, Object>();
conditions.put("kw", "solr");// 指定搜索词keyword
conditions.put("catalogId", "5");// 指定所在栏目id
page.setConditions(conditions);
SolrService.getByPage(page);
for (Object o : page.getDatas()) {
Article a = (Article) o;
System.out.println(a.getTitle());
}
}
/**
相关说明:
1,因为我想在标题和正文中进行搜索,而且我使用了copyField将title和
content都拷贝到了拷贝字段text中,所以我这里在搜索的时候不需要写成
"title:"+ckw+" OR " + "content:"+ckw,而直接使用ckw即可;因为
catalogId没有在拷贝字段中,搜索时需要指定所在字段,
即"catalog_id:"+cCatalogId。
**/