`
l514941630
  • 浏览: 46162 次
  • 性别: Icon_minigender_2
  • 来自: 成都
社区版块
存档分类
最新评论

solr二次开发之solrj(转载)

阅读更多
Solrj已经是很强大的solr客户端了。它本身就包装了httpCliet,以完全对象的方式对solr进行交互。很小很好很强大。
    不过在实际使用中,设置SolrQuery 的过程中,为了设置多个搜索条件和排序规则等等参数,我们往往会陷入并接字符串的地步,实在是很丑陋,不符合面向对象的思想。扩展性几乎为0,。基于这点,开发了一个小东西,我们只需要设置搜索对象,将对象扔给后台就可以了。
    比如,我们搭建的solr服务支持某10个字段的搜索,我们要搜索其中的一些,那么我们只需要传入要搜索的对象POJO,将要搜索的字段内容,set到POJO对象对应额字段即可。
    比如如下一个类:

package org.uppower.tnt.biz.core.manager.blog.dataobject;  
  
/** 
 * @author yingmu 
 * @version 2010-7-20 下午01:00:55 
 */  
public class SolrPropertyDO {  
    private String auction_id;  
    private String opt_tag;  
    private String exp_tag;  
    private String title;  
    private String desc;  
    private String brand;  
    private String category;  
    private String price;  
    private String add_prov;  
    private String add_city;  
    private String quality;  
    private String flag;  
    private String sales;  
    private String sellerrate;  
    private String selleruid;  
    private String ipv15;  
  
    public String getAuction_id() {  
        return auction_id;  
    }  
  
    public void setAuction_id(String auctionId) {  
        auction_id = auctionId;  
    }  
  
    ……  
  
    public String getExp_tag() {  
        return exp_tag;  
    }  
  
    public void setExp_tag(String expTag) {  
        exp_tag = expTag;  
    }  
}  

那么我们在定义搜索对象时候,就按照如下设置:
SolrPropertyDO propertyDO = new SolrPropertyDO();  
        propertyDO.setAdd_city("(杭州AND成都)OR北京");  
        propertyDO.setTitle("丝绸OR剪刀");  
         ……  

设置排序条件,也是类似的做法:
SolrPropertyDO compositorDO = new SolrPropertyDO();  
        compositorDO.setPrice ("desc");  
        compositorDO.setQuality ("asc");  
         ……  

  将定义好的两个对象扔给后面的接口就可以了。

     接口函数querySolrResult传入四个参数,其中包含搜索字段对象,排序条件对象。为了提供类似limit的操作,用于分页查询,提供了startIndex和pageSize。
     函数querySolrResultCount是单纯为了获得搜索条数,配合分页使用。
    以下是定义的接口:

package org.uppower.tnt.biz.core.manager.blog;  
  
import java.util.List;  
  
import org.uppower.tnt.biz.core.manager.isearch.dataobject.SolrPropertyDO;  
  
/** 
 * @author yingmu 
 * @version 2010-7-20 下午03:51:15 
 */  
public interface SolrjOperator {  
  
    /** 
     * 获得搜索结果 
     *  
     * @param propertyDO 
     * @param compositorDO 
     * @param startIndex 
     * @param pageSize 
     * @return 
     * @throws Exception 
     */  
    public List<Object> querySolrResult(Object propertyDO,  
            Object compositorDO, Long startIndex, Long pageSize)  
            throws Exception;  
  
    /** 
     * 获得搜索结果条数 
     *  
     * @param propertyDO 
     * @param compositorDO 
     * @return 
     * @throws Exception 
     */  
    public Long querySolrResultCount(SolrPropertyDO propertyDO,  
            Object compositorDO) throws Exception;  
  
}  

实现逻辑为,首先将传入的两个实体对象,解析为<K,V>结构的Map当中,将解析完成的Map放入solrj实际的搜索对象当中。返回的对象为solrj的API提供的SolrDocument,其中结果数量为直接返回SolrDocumentList对象的getNumFound()
    具体实现类:

package org.uppower.tnt.biz.core.manager.blog;  
  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
import java.util.TreeMap;  
  
import org.apache.solr.common.SolrDocumentList;  
  
import org.uppower.tnt.biz.core.manager.isearch.common.SolrjCommonUtil;  
import org.uppower.tnt.biz.core.manager.isearch.dataobject.SolrPropertyDO;  
import org.uppower.tnt.biz.core.manager.isearch.solrj.SolrjQuery;  
  
/** 
 * @author yingmu 
 * @version 2010-7-20 下午03:51:15 
 */  
public class DefaultSolrOperator implements SolrjOperator {  
      
    private Logger logger = LoggerFactory.getLogger(this.getClass());  
    private SolrjQuery solrjQuery;  
  
    public void setSolrjQuery(SolrjQuery solrjQuery) {  
        this.solrjQuery = solrjQuery;  
    }  
  
    @Override  
    public List<Object> querySolrResult(Object propertyDO,  
            Object compositorDO, Long startIndex, Long pageSize)  
            throws Exception {  
        Map<String, String> propertyMap = new TreeMap<String, String>();  
        //排序有顺序,使用TreeMap  
        Map<String, String> compositorMap = new TreeMap<String, String>();  
        try {  
            propertyMap = SolrjCommonUtil.getSearchProperty(propertyDO);  
            compositorMap = SolrjCommonUtil.getSearchProperty(compositorDO);  
        } catch (Exception e) {  
            logger.error("SolrjCommonUtil.getSearchProperty() is error !"+ e);  
        }  
        SolrDocumentList solrDocumentList = solrjQuery.query(propertyMap, compositorMap,  
                startIndex, pageSize);  
        List<Object> resultList = new ArrayList<Object>();  
        for (int i = 0; i < solrDocumentList.size(); i++) {  
            resultList.add(solrDocumentList.get(i));  
        }  
        return resultList;  
    }  
  
    @Override  
    public Long querySolrResultCount(SolrPropertyDO propertyDO,  
            Object compositorDO) throws Exception {  
        Map<String, String> propertyMap = new TreeMap<String, String>();  
        Map<String, String> compositorMap = new TreeMap<String, String>();  
        try {  
            propertyMap = SolrjCommonUtil.getSearchProperty(propertyDO);  
            compositorMap = SolrjCommonUtil.getSearchProperty(compositorDO);  
        } catch (Exception e) {  
            logger.error("SolrjCommonUtil.getSearchProperty() is error !" + e);  
        }  
        SolrDocumentList solrDocument = solrjQuery.query(propertyMap, compositorMap,  
                null, null);  
        return solrDocument.getNumFound();  
    }  
  
}  

其中,对象的解析式利用反射原理,将实体对象中不为空的值,以映射的方式,转化为一个Map,其中排序对象在转化的过程中,使用TreeMap,保证其顺序性。
    解析公共类实现如下:

package org.uppower.tnt.biz.core.manager.blog.solrj;  
  
import java.net.MalformedURLException;  
import java.util.Map;  
  
import org.apache.solr.client.solrj.SolrQuery;  
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;  
import org.apache.solr.client.solrj.response.QueryResponse;  
import org.apache.solr.common.SolrDocumentList;  
  
/** 
 * @author yingmu 
 * @version 2010-7-20 下午02:57:04 
 */  
public class SolrjQuery {  
    private String url;  
    private Integer soTimeOut;  
    private Integer connectionTimeOut;  
    private Integer maxConnectionsPerHost;  
    private Integer maxTotalConnections;  
    private Integer maxRetries;  
    private CommonsHttpSolrServer solrServer = null;  
    private final static String ASC = "asc";  
  
    public void init() throws MalformedURLException {  
        solrServer = new CommonsHttpSolrServer(url);  
        solrServer.setSoTimeout(soTimeOut);  
        solrServer.setConnectionTimeout(connectionTimeOut);  
        solrServer.setDefaultMaxConnectionsPerHost(maxConnectionsPerHost);  
        solrServer.setMaxTotalConnections(maxTotalConnections);  
        solrServer.setFollowRedirects(false);  
        solrServer.setAllowCompression(true);  
        solrServer.setMaxRetries(maxRetries);  
    }  
  
    public SolrDocumentList query(Map<String, String> propertyMap,  
            Map<String, String> compositorMap, Long startIndex, Long pageSize)  
            throws Exception {  
        SolrQuery query = new SolrQuery();  
        // 设置搜索字段  
        if (null == propertyMap) {  
            throw new Exception("搜索字段不可为空!");  
        } else {  
            for (Object o : propertyMap.keySet()) {  
                StringBuffer sb = new StringBuffer();  
                sb.append(o.toString()).append(":");  
                sb.append(propertyMap.get(o));  
                String queryString = addBlank2Expression(sb.toString());  
                query.setQuery(queryString);  
            }  
        }  
        // 设置排序条件  
        if (null != compositorMap) {  
            for (Object co : compositorMap.keySet()) {  
                if (ASC == compositorMap.get(co)  
                        || ASC.equals(compositorMap.get(co))) {  
                    query.addSortField(co.toString(), SolrQuery.ORDER.asc);  
                } else {  
                    query.addSortField(co.toString(), SolrQuery.ORDER.desc);  
                }  
            }  
        }  
          
        if (null != startIndex) {  
            query.setStart(Integer.parseInt(String.valueOf(startIndex)));  
        }  
        if (null != pageSize && 0L != pageSize.longValue()) {  
            query.setRows(Integer.parseInt(String.valueOf(pageSize)));  
        }  
        try {  
            QueryResponse qrsp = solrServer.query(query);  
            SolrDocumentList docs = qrsp.getResults();  
            return docs;  
        } catch (Exception e) {  
            throw new Exception(e);  
        }  
    }  
  
    private String addBlank2Expression(String oldExpression) {  
        String lastExpression;  
        lastExpression = oldExpression.replace("AND", " AND ").replace("NOT",  
                " NOT ").replace("OR", " OR ");  
        return lastExpression;  
    }  
  
    public Integer getMaxRetries() {  
        return maxRetries;  
    }  
  
    ……  
        
        public void setMaxTotalConnections(Integer maxTotalConnections) {  
        this.maxTotalConnections = maxTotalConnections;  
    }  
}  

整个实现是在Spring的基础上完成的,其中SolrjQuery的init()方法在Spring容器启动是初始化。Init()方法内的属性,也是直接注入的。上层与下层之间也完全用注入的方式解决。具体配置就不贴不出来了,大家都会。
整个代码很简陋,但是几乎支持了你想要搜索的条件设置,而且不会暴露任何与solr相关的内容给上层调用,使整个搜索几乎以sql语言的思想在设置条件。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics