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> 转换为指定业务对象总结的主要内容,如果未能解决你的问题,请参考以下文章

solr全文检索,建立的文件索引,检索不出正确结果

Solr---有趣的全文检索(原理篇)

solr 排序与文档分数计算

Solr

lucene&solr全文检索_3查询索引

Solr:搜索带连字符的术语给出 0 个结果