Solr 检索结果集List<SolrDocument> 转换为指定业务对象总结
Posted 在奋斗的大道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Solr 检索结果集List<SolrDocument> 转换为指定业务对象总结相关的知识,希望对你有一定的参考价值。
前提说明:从solr结果集中取数据,取到了结果集,但是结果集是一个map,而我想要得到的是一个对象,怎么处理呢? 我总计如下三种方法:
第一种:solrDocument中提供了一个获取每个field对应值的方法,使用此方法获取所有的field对应的值,set到类中:
功能代码如下:
private List<Product> setProductData(SolrDocumentList list)
List<Product> datas = new ArrayList<Product>();
String jsonStr = "";
Product item = null;
for (SolrDocument solrDocument : list)
item = new Product();
item.setId((Long)solrDocument.getFieldValue("id"));
item.setProduct(solrDocument.getFieldValue("product").toString());
item.setOrderDate((Date)solrDocument.getFieldValue("orderDate"));
...
datas.add(item);
return datas;
第二种:使用了BeanUtils工具+反射,通过反射,获取solrDocument中的所有key和value,然后利用BeanUtils.setProperty(bean, name, value);方法,给Product设置属性,这样也有缺点,就是反射过程中容易出现异常,另外更严重的是此方法对Date类型的属性不能处理,而Product中有Date类型的属性,如果非要使用这种方案,就要写date类型的转换类,无疑增加了代码量。
private List<Product> setProductData(SolrDocumentList list)
List<Product> datas = new ArrayList<Product>();
String jsonStr = "";
Product item = null;
for (SolrDocument solrDocument : list)
item = new Product();
Long id =SimpleTypeConverterUtil.convertIfNecessary(solrDocument.getFieldValue("id",Lon.class)
BeanUtils.setProperty(item, "id", id);
String product = SimpleTypeConverterUtil.convertIfNecessary(solrDocument.getFieldValue("product",String.class)
BeanUtils.setProperty(item, "product", product);
Date orderDate = SimpleTypeConverterUtil.convertIfNecessary(solrDocument.getFieldValue("orderDate,Date.class)
BeanUtils.setProperty(item, "orderDate", orderDate);
...
datas.add(item);
return datas;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.SimpleTypeConverter;
import com.zzg.common.convert.DateEditor;
/**
* spring type converter
* @author Administrator
*
*/
public class SimpleTypeConverterUtil
public static final Logger log = LoggerFactory.getLogger(SimpleTypeConverterUtil.class);
private static final SimpleTypeConverter typeConverterDelegate = new SimpleTypeConverter();
static
typeConverterDelegate.registerCustomEditor(Date.class, new DateEditor());
/**
* @param <T>
* @param value 待转换值,一般字符串
* @param requiredType 转后类型类对象
* @return
*/
public static <T> T convertIfNecessary(Object value, Class<T> requiredType)
T rs = null;
try
rs = typeConverterDelegate.convertIfNecessary(value, requiredType);
catch (Exception e)
log.info(e.getMessage());
if(requiredType == int.class || requiredType == Integer.class)
rs = (T)Integer.valueOf(0);
return rs;
package com.zzg.common.convert;
import java.beans.PropertyEditorSupport;
import com.zzg.common.util.DateUtils;
public class DateEditor extends PropertyEditorSupport
@Override
public void setAsText(String text) throws IllegalArgumentException
setValue(DateUtils.formatDateStr(text));
package com.zzg.common.util;
import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*/
public class DateUtils
public static final Logger log = LoggerFactory.getLogger(DateUtils.class);
public static final String YYYY = "yyyy" ;
public static final String YYYY_MM = "yyyy-MM" ;
public static final String YYYY_MM_DD = "yyyy-MM-dd" ;
public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss" ;
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss" ;
private static String[] parsePatterns =
YYYY_MM_DD , YYYY_MM_DD_HH_MM_SS , "yyyy-MM-dd HH:mm" , YYYY_MM ,
"yyyy/MM/dd" , "yyyy/MM/dd HH:mm:ss" , "yyyy/MM/dd HH:mm" , "yyyy/MM" ,
"yyyy.MM.dd" , "yyyy.MM.dd HH:mm:ss" , "yyyy.MM.dd HH:mm" , "yyyy.MM";
/**
* 获取当前Date型日期
*
* @return Date() 当前日期
*/
public static Date getNowDate()
return new Date();
/**
* 获取当前日期, 默认格式为yyyy-MM-dd
*
* @return String
*/
public static String getDate()
return dateTimeNow(YYYY_MM_DD);
public static final String getTime()
return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
public static final String dateTimeNow()
return dateTimeNow(YYYYMMDDHHMMSS);
public static final String dateTimeNow(final String format)
return parseDateToStr(format, new Date());
public static final String dateTime(final Date date)
return parseDateToStr(YYYY_MM_DD, date);
public static final String parseDateToStr(final String format, final Date date)
if (date == null)
return null;
Format formatter = new SimpleDateFormat(format);
return formatter.format(date);
/**
* 获取服务器启动时间
*/
public static Date getServerStartDate()
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time);
private static final List<DateFormat> formarts = new ArrayList<>(5);
static
formarts.add(new SimpleDateFormat("yyyy-MM"));
formarts.add(new SimpleDateFormat("yyyy-MM-dd"));
formarts.add(new SimpleDateFormat("yyyy-MM-dd hh:mm"));
formarts.add(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
formarts.add(new SimpleDateFormat("yyyy.MM.dd"));
public static Date formatDateStr(String source)
String value = source.trim();
if ("".equals(value))
return null;
try
if (source.matches("^\\\\d4-\\\\d1,2$"))
return formarts.get(0).parse(source);
else if (source.matches("^\\\\d4-\\\\d1,2-\\\\d1,2$"))
return formarts.get(1).parse(source);
else if (source.matches("^\\\\d4-\\\\d1,2-\\\\d1,2 1\\\\d1,2:\\\\d1,2$"))
return formarts.get(2).parse(source);
else if (source.matches("^\\\\d4-\\\\d1,2-\\\\d1,2 1\\\\d1,2:\\\\d1,2:\\\\d1,2$"))
return formarts.get(3).parse(source);
else if (source.matches("^\\\\d4.\\\\d1,2.\\\\d1,2$"))
return formarts.get(4).parse(source);
else
throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
catch (Exception e)
log.warn("DateUtils.formatDateStr error", e);
return null;
/**
* 计算两个时间差
*/
public static String getDatePoor(Date endDate, Date nowDate)
long nd = (long)1000 * 24 * 60 * 60;
long nh = (long)1000 * 60 * 60;
long nm = (long)1000 * 60;
// 获得两个时间的毫秒时间差异
long diff = endDate.getTime() - nowDate.getTime();
// 计算差多少天
long day = diff / nd;
// 计算差多少小时
long hour = diff % nd / nh;
// 计算差多少分钟
long min = diff % nd % nh / nm;
// 计算差多少秒//输出结果
return day + "天" + hour + "小时" + min + "分钟" ;
/**
* 增加日期
*
* @param date
* @param field Calendar.MONTH,Calendar.DAY_OF_YEAR
* @param amount 正数为将来时间, 负数为过去时间
* @return
*/
public static Date getAddDate(Date date, int field, int amount)
Calendar cl = Calendar.getInstance();
cl.setTime(date);
cl.add(field, amount);
Date dateFrom = cl.getTime();
return dateFrom;
/**
* 获取前几周
*
* @param date
* @return
*/
public static Date getBeforeWeek(Date date, int week)
return getAddDate(date, Calendar.WEEK_OF_YEAR, week);
/**
* 获取前几天
*
* @param date
* @return
*/
public static Date getBeforeDay(Date date, int day)
return getAddDate(date, Calendar.DAY_OF_YEAR, day);
/**
* 获取前几月
*
* @param date
* @return
*/
public static Date getBeforeMouth(Date date, int mouth)
return getAddDate(date, Calendar.MONTH, mouth);
/**
* 获取前几年
*
* @param date
* @return
*/
public static Date getBeforeYear(Date date, int year)
return getAddDate(date, Calendar.YEAR, year);
/**
* 获取后几周
*
* @param date
* @return
*/
public static Date getAfterWeek(Date date,int week)
return getAddDate(date, Calendar.WEEK_OF_YEAR, week);
/**
* 获取后几天
*
* @param date
* @return
*/
public static Date getAfterDay(Date date, int day)
return getAddDate(date, Calendar.DAY_OF_YEAR, day);
/**
* 获取后几月
*
* @param date
* @return
*/
public static Date getAfterMouth(Date date, int month)
return getAddDate(date, Calendar.MONTH, month);
/**
* 获取后几年
*
* @param date
* @return
*/
public static Date getAfterYear(Date date, int year)
return getAddDate(date, Calendar.YEAR, year);
第三种:先将solrDocument类转换为json,然后再将此json转换为我要的业务对象类
/**
*
* @Title: getCommonsHttpSolrServer @Description: HttpSolrClient
* 初始化 @param: @return @param: @throws
* MalformedURLException @return: HttpSolrClient @throws
*/
protected HttpSolrServer getHttpSolrServer(HttpServletRequest request, String solrCoreName)
String solruri = "http://" + request.getServerName() + ":" + request.getServerPort() + "/solr-webapp/";
solruri = ApplicationPropertiesHolder.getProperty("request.solr.uri", solruri);
solruri = solruri + solrCoreName + "/";
HttpSolrServer server =new HttpSolrServer(solruri);
server.setParser(new XMLResponseParser()); // binary parser is used by
// 设置重试次数
server.setMaxRetries(2);
// 设置超时时间
server.setConnectionTimeout(5000);
return server;
// 设置查询条件
public String getQueryCondition(String text)
if(StringUtils.isNotEmpty(text))
StringBuilder builder = new StringBuilder();
List<String> filterStr = Arrays.asList(text.split("\\\\s+"));
List<String> list = filterStr.stream().map(item ->
return "text:" + "*".concat(item).concat("*");
).collect(Collectors.toList());
for (int i = 0; i < list.size(); i++)
builder.append(list.get(i));
if (i < list.size() - 1)
builder.append(" and ");
return builder.toString();
return StringUtils.EMPTY;
@RequestMapping(value = "/querySolr", method = RequestMethod.POST )
@ResponseBody
@ApiOperation(value = "工程档案检索")
@ApiImplicitParams(
@ApiImplicitParam(name = "text", value = "检索关键字", required = true, dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "type", value = "检索类型", required = true, dataType = "String", paramType = "query"),
@ApiImplicitParam(name = "page", value = "页码", required = false, dataType = "Integer", paramType = "query"),
@ApiImplicitParam(name = "limit", value = "页次", required = false, dataType = "Integer", paramType = "query")
)
public Result querySolr(HttpServletRequest request,
@RequestBody(required = false) HashMap<String, Object> entity)
String type = SimpleTypeConverterUtil.convertIfNecessary(entity.get("type"), String.class);
entity.remove("type");
if(StringUtils.isEmpty(type))
return Result.error("检索必须指定类型");
// 构建查询条件
SolrQuery query = new SolrQuery();
// 分页参数
PageParam rb = super.initPageBounds(entity);
query.setStart((rb.getPageNo() - 1) * rb.getLimit() > 0
? (rb.getPageNo() - 1) * rb.getLimit() : 0);
query.setRows(rb.getLimit());
// 设置查询条件
String condition = this.getQueryCondition(SimpleTypeConverterUtil.convertIfNecessary(entity.get("text"), String.class));
if (StringUtils.isNotEmpty(condition))
logger.error("query 条件:" + condition);
query.setQuery(condition);
// solr 查询
QueryResponse queryResponse = null;
try
HttpSolrServer httpSolrServer = this.getHttpSolrServer(request, type);
queryResponse = httpSolrServer.query(query);
catch (SolrServerException e)
// TODO Auto-generated catch block
logger.error("solr 检索异常:", e.getMessage(), e);
return Result.error("档案检索异常");
// solr 查询结果分页
List<SolrDocument> list = queryResponse.getResults();
if(CollectionUtils.isEmpty(list))
return Result.error("档案未检索到相关数据");
PageData<Object> page = getSolrResult(rb, queryResponse, list, type);
return Result.ok().setData(page);
/**
* 转换solr 检索结果对象
* @param rb
* @param queryResponse
* @param list
* @param type
* @return
*/
private PageData<Object> getSolrResult(PageParam rb, QueryResponse queryResponse, List<SolrDocument> list, String type)
List<Object> maps = list.stream().map(item->
String json = JSON.toJSONString(item);
if(SolrIndexEnum.ArchInfo.getIndex().equalsIgnoreCase(type))
return JSON.parseObject(json, ArchInfo.class);
else if(SolrIndexEnum.ContractUnitInfo.getIndex().equalsIgnoreCase(type))
return JSON.parseObject(json, ContractUnitInfo.class);
else if(SolrIndexEnum.EngBaseInfo.getIndex().equalsIgnoreCase(type))
return JSON.parseObject(json, EngBaseInfo.class);
else
return JSON.parseObject(json, IndividualInfo.class);
).collect(Collectors.toList());
PageData<Object> page = new PageData<Object>();
page.setData(maps);
page.setTotalCount(queryResponse.getResults().getNumFound() != 0 ? queryResponse.getResults().getNumFound() : 0);
page.setPageSize(rb.getLimit());
page.setPageNum(rb.getPageNo());
return page;
以上是关于Solr 检索结果集List<SolrDocument> 转换为指定业务对象总结的主要内容,如果未能解决你的问题,请参考以下文章