博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(三)solrj使用
阅读量:6275 次
发布时间:2019-06-22

本文共 15141 字,大约阅读时间需要 50 分钟。

  hot3.png

1、查询

(1)获取cloud solr server

 Collapse source

/** * 获取cloud solr server * @author caibosi * @created 2013-12-04 */public enum SolrServerManager {    CONTRACT_LIST("collection1"),    REQUEST_AUDIT_LIST("collection2");     String serverName;     Logger logger = LoggerFactory.getLogger(SolrServerManager.class);     final int zkClientTimeout = 20000; // 心跳20秒     final int zkConnectTimeout = 10000; // 连接时间10秒    //如果采用的cloud server, 这个地址为zookeeper的地址,192.168.4.129:9983     final String zkHost = "ct.solrcloud.host";     CloudSolrServer cloudSolrServer = null;    private SolrServerManager(String serverName){        this.serverName = serverName;        try {            cloudSolrServer = new CloudSolrServer(ConfigUtil.getValueByKey(this.zkHost));            logger.info("### get solr server");        } catch (MalformedURLException e) {            logger.error("connect solr server error",e);        }        cloudSolrServer.setDefaultCollection(this.serverName);        cloudSolrServer.setZkClientTimeout(this.zkClientTimeout);        cloudSolrServer.setZkConnectTimeout(this.zkConnectTimeout);    }    public CloudSolrServer getSolrServer(){        return cloudSolrServer;    }}

 

(2)查询实例

 Collapse source

/**     * 封装solr查询方法     * @author caibosi     * @created 2013-12-05     * @param query     * @return     * @throws SolrServerException     */    public SolrDocumentList getSolrDocumentList(SolrQuery query) throws SolrServerException {        CloudSolrServer server = SolrServerManager.CONTRACT_LIST.getSolrServer();        QueryResponse response = server.query(query);        SolrDocumentList docs = response.getResults();        logger.info("### query:"+ decodeByUTF8(query.toString()));        logger.info("### solr response:"+ToStringBuilder.reflectionToString(response));        return docs;    }    // 将字符串 UTF-8 解码    public String decodeByUTF8(String str) {        String target;        try {            target = URLDecoder.decode(str, "UTF-8");        } catch (Exception e) {            logger.error("解码出错!", e);            return str;        }        return target;    }    /**     * contract/list     * 根据合同编号 或 合同名称查询     *     * 抛出RuntimeException的话     * 会导致事务的回滚     * 影响到页面报错     *     * 因而抛出Exception     * http://xdy2008.iteye.com/blog/1973725     *     * @author caibosi     * @created 2013-12-05     * @param keyword     * @param page     * @return     */    public List
 getContractListByKeyword(String keyword,Page page) throws Exception {        boolean solrEnabled = ConfigUtil.getValue2BooleanByKey("solr.enabled");        if(solrEnabled == false)            throw new Exception("solr service disabled");        long start = System.currentTimeMillis();        logger.info("### query contract list using solr, keyword :"+keyword);        SolrQuery query = new SolrQuery();        query.setQuery("contractName:"+keyword+" OR contractNum:"+keyword);        SolrDocumentList docs = getSolrDocumentList(query);        List
 contractIds = new ArrayList
();        if(CollectionUtils.isEmpty(docs) == false){            for(SolrDocument doc : docs){                String contractId = MapUtils.getString(doc,"id");                if(contractId!=null)                    contractIds.add(contractId);            }        }        List
 contractList = new ArrayList
();        if(CollectionUtils.isEmpty(contractIds) == false){            contractList = contractDao.findByIds(contractIds);        }        long end = System.currentTimeMillis();        logger.info("### get by solr,cost:"+(end-start));        return contractList;    }

 

2、植入业务代码

     植入方案:

(1)在原有的代码里头增加solr查询逻辑

/**	 * @param contractListBean	 * @param page	 * @return	 */    @SolrCached	public List
 findContractListByContractListBean(ContractListBean contractListBean,                                                           Page page) { if (StringUtil.isNotBlank(contractListBean.getKeyword())) { // 有关键字,先等值匹配,再like            long start = System.currentTimeMillis();            /**             * spring aop 不支持拦截方法内部再调同一类的其他方法             * 先写在这里测试下solr功能             */            try {                List
 list = solrService.getContractListByKeyword(contractListBean.getKeyword(),page);                return list;            } catch (Exception e) {                logger.error("get from solr by keyword error,get from db instead",e);            }            logger.info("### query key word from db :"+contractListBean.getKeyword()); List
 list = findContractListByContractListBeanInternal(contractListBean, page, true);            long end = System.currentTimeMillis();            logger.info("### cost:"+(end-start));//            if (list.size() == 0) {//                return findContractListByContractListBeanInternal(contractListBean, page, true);//            } else {//                return list;//            } return list; } else { // 没关键字,只查一次 return findContractListByContractListBeanInternal(contractListBean, page, true); } }

 Collapse source

         优点:明了,直接,程序员看着直白,知道这里有经过solr的缓存

         缺点:在编程的时候植入,业务逻辑与缓存逻辑混杂在一起

 

(2)利用aop,动态植入

原有的方法仅仅加一个注解

 Collapse source

/**     * @param contractListBean     * @param page     * @return     */    @SolrCached(SolrCachedMethod.CONTRACT_LIST_KEYWORD)    public List
 findContractListByContractListBean(ContractListBean contractListBean,                                                             Page page) {        if (StringUtil.isNotBlank(contractListBean.getKeyword())) {            // 有关键字,先等值匹配,再like            long start = System.currentTimeMillis();            List
 list = contractService.findContractListByContractListBeanInternal(contractListBean, page,                    true);            long end = System.currentTimeMillis();            logger.info("### cost:"+(end-start));//            if (list.size() == 0) {//                return findContractListByContractListBeanInternal(contractListBean, page, true);//            } else {//                return list;//            }            return list;        } else {            // 没关键字,只查一次            return contractService.findContractListByContractListBeanInternal(contractListBean, page, true);        }    }

 

在拦截器里头处理

/** * 拦截service相关方法 * 使用solr进行查询 * @author caibosi * @created 2013-12-05 */@Aspect@Componentpublic class SolrInterceptor {    private final Logger logger = LoggerFactory.getLogger(SolrInterceptor.class);    @Resource    private SolrService solrService;    /**     * 拦截带有SolrCached的方法     * @param pjp     * @return     * @throws Throwable     */    @Around("@annotation(solrCached)")    public Object getResultBySolr(ProceedingJoinPoint pjp,SolrCached solrCached) throws Throwable {        try{            if(solrCached.value() == SolrCachedMethod.CONTRACT_LIST_KEYWORD){                Object[] args = pjp.getArgs();                ContractListBean queryBean = (ContractListBean) args[0];                Page page = (Page) args[1];                if(queryBean!=null && queryBean.getKeyword()!=null){                    return  solrService.getContractListByKeyword(queryBean.getKeyword(),page);                }                logger.info("### into findContractListByContractListBean");            }        }catch (Exception e){            logger.error("query solr error,query db instead",e);        }        return pjp.proceed(pjp.getArgs());    }}

 Collapse source

         优点:与业务逻辑分离开

         缺点:程序员可能不知道此处会被拦截,进行solr查询

                   因而,采用注解的形式告知,但spring aop不支持同一类A方法内部调B方法中B方法的拦截,因而找到最细粒度的方法进行拦截可能优点困难,因而这个方法可能没办法拦截到。

         解决方法:1、改造原来方法(移动其他类,但是改动大) 2、采用兼容模式,无法被拦截的,直接在代码里头写,可以被拦截的就在interceptor里头写、

 

3、同步索引

     索引的同步与业务逻辑关联比较大,每个solr缓存的数据的触发条件都不大一样。

   (1)增加

          根据contract的add_time,对solr进行增量同步

          方案1:采用delta import, 在配置文件里配置,同时使用crontab 定时执行该命令的url

          方案2:在java里头增量同步,可以在数据库里记录同步,把失败的再重来

public SolrImortResult importContractListByPage(Date start,Date end,Page page){        List
 contractList = contractDao.findByAddTime(start,end,page);        if(CollectionUtils.isEmpty(contractList)){            return new SolrImortResult(new Date(),new Date(),0);        }else{            logger.info("#### begin to update count:"+contractList.size());        }        List
 inputDocs = new ArrayList
();        SolrImortResult result = new SolrImortResult();        int updateCount = -1;        for(Contract ct : contractList){            SolrInputDocument doc = new SolrInputDocument();            doc.addField("contractId",ct.getContractId());            doc.addField("contractNum",ct.getContractNum());            doc.addField("contractName",ct.getContractName());            inputDocs.add(doc);        }        CloudSolrServer server = SolrServerManager.CONTRACT_LIST.getSolrServer();        try {            server.connect();            server.add(inputDocs);            UpdateResponse response = server.commit();            if(response!=null){               logger.info("### update to solr for page:"+page.getPageNo()+";response:"+ToStringBuilder.reflectionToString(response));                   updateCount = page.getPageSize();            }        } catch (Exception e) {            logger.error("update contract list to solr error",e);            updateCount = -1;        }        Date startTime = contractList.get(0).getAddTime();        Date endTime = contractList.get(contractList.size()-1).getAddTime();        result.setStartTime(startTime);        result.setEndTime(endTime);        result.setUpdateCount(updateCount);        return result;    }

 Collapse source

   (2)更新

         add方法添加字段,set方法更新

package com.persia.solrj;import org.apache.solr.client.solrj.SolrServerException;import org.apache.solr.client.solrj.impl.CloudSolrServer;import org.apache.solr.common.SolrInputDocument;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;import java.io.IOException;import java.util.*;/** * solr服务 * 获取solr server * @author caibosi * @created 2013-12-04 */@Servicepublic class SolrTestService {    private static final Logger logger = LoggerFactory.getLogger(SolrTestService.class);    /**     * 这种有效果,删除再添加     * 但不知道与map方式的区别     * 如果是add全部字段,其实是没有区别滴     * 如果add部分字段,没有add的字段会丢失掉     * @throws java.io.IOException     * @throws org.apache.solr.client.solrj.SolrServerException     */    public void updateByAdd() throws IOException, SolrServerException {        CloudSolrServer server = SolrServerManager.CONTRACT_SEARCH.getSolrServer();        server.connect();        SolrInputDocument doc = new SolrInputDocument();        doc.addField("contractId","74acd736-f84e-11e2-8dea-00222822153f");        doc.addField("contractName","测试update操作23");        doc.addField("contractNum","测试update操作33");        server.add(doc);        server.commit();        logger.info("### update success,contractId:{283a8436-481c-11e3-8dea-00222822153f}");    }    /**     * 下面这种纯属字面上的误会     * 实际上会更新整个文档     * 假设文档原来十几个字段     * 这种方式会替换为3个字段(如下)     * http://osdir.com/ml/solr-user.lucene.apache.org/2012-07/msg01065.html     *     * not setting internal flags for the       indexer to treat the SolrInputDocument differently based on if set or       add was called     *     * @throws java.io.IOException     * @throws org.apache.solr.client.solrj.SolrServerException     */    public void updateBySet() throws IOException, SolrServerException {        CloudSolrServer server = SolrServerManager.CONTRACT_SEARCH.getSolrServer();        server.connect();        SolrInputDocument doc = new SolrInputDocument();        //如果id也用setfield的话,当文档不存在的时候,也会创建        doc.addField("contractId", "74acd736-f84e-11e2-8dea-00222822153f");        doc.setField("contractNum","234254646664c1set");        doc.setField("contractName", "测试update操作3set");        server.add(doc);        server.commit();        logger.info("### update success,contractId:{283a8436-481c-11e3-8dea-00222822153f}");    }    /**     * 下面这种才是正确的update方式     * {     *"add" : {     *"doc" : {     *"id":"12345",     *"foo":{"set":null},     *"bar":{"set":"baz"}     *}     *}     *}     * @throws java.io.IOException     * @throws org.apache.solr.client.solrj.SolrServerException     */    public void updateByMap() throws IOException, SolrServerException {        CloudSolrServer server = SolrServerManager.CONTRACT_SEARCH.getSolrServer();        server.connect();        SolrInputDocument doc = new SolrInputDocument();        doc.addField("contractId","8b0e8874-5640-11e3-8dea-00222822153f");        Map
 value = new HashMap
();        value.put("set","ww测试partial");        doc.addField("contractName",value);        Map
 value1 = new HashMap
();        value1.put("set","wwc987654321");        doc.addField("contractNum",value1);        server.add(doc);        server.commit();        logger.info("### update success,contractId:{283a8436-481c-11e3-8dea-00222822153f}");    }   public void test() throws IOException, SolrServerException {       CloudSolrServer server = SolrServerManager.CONTRACT_SEARCH.getSolrServer();       server.connect();//       ZkStateReader zkStateReader = server.getZkStateReader();//       ClusterState state = zkStateReader.getClusterState();//       System.out.println("### "+state);////       SolrQuery query = new SolrQuery();//       query.setQuery("contractName:测试选择商户改进");//       try {//           QueryResponse response = server.query(query);//           SolrDocumentList docs = response.getResults();//           System.out.println("### count:"+docs.getNumFound());//           System.out.println("### cost:"+response.getQTime());////           for(SolrDocument doc:docs){//               String name = (String) doc.getFieldValue("contractName");//               String id = (String)doc.getFieldValue("contractId");//               System.out.println("### id:"+id+";name:"+name);//           }//       } catch (SolrServerException e) {//           e.printStackTrace();//       }       SolrInputDocument doc = new SolrInputDocument();       doc.addField("contractId","g283a8436-481c-11e3-8dea-00222822153f");       doc.addField("contractNum", "g234254646664c1");       doc.addField("contractName", "g测试update操作3");//       Map
 value = new HashMap
();//       value.put("set","测试partial");//       doc.addField("contractName",value);       server.add(doc);       server.commit();       logger.info("### update success,contractId:{283a8436-481c-11e3-8dea-00222822153f}");//       server.shutdown();//      CloudSolrServer server1 = SolrServerManager.CONTRACT_LIST.getSolrServer();//       System.out.println("### server1:"+server1.toString());////       CloudSolrServer server2 = SolrServerManager.CONTRACT_LIST.getSolrServer();//       System.out.println("### server2:"+server2.toString());   }    public static void main(String[] args){    }}

   (3)删除

 Collapse source

public void clearContractSearch() throws IOException, SolrServerException {        CloudSolrServer server = SolrServerManager.CONTRACT_SEARCH.getSolrServer();        server.connect();        server.deleteByQuery( "*:*" );// delete everything!        server.commit();}

 

 

转载于:https://my.oschina.net/scipio/blog/214300

你可能感兴趣的文章
浅谈MySQL 数据库性能优化
查看>>
《UNIX/Linux 系统管理技术手册(第四版)》——1.10 其他的权威文档
查看>>
灵动空间 创享生活
查看>>
《UNIX网络编程 卷1:套接字联网API(第3版)》——8.6 UDP回射客户程序:dg_cli函数...
查看>>
不要将时间浪费到编写完美代码上
查看>>
《第一桶金怎么赚——淘宝开店创业致富一册通》一一第1章 创业梦想,怎样起步...
查看>>
基于容器服务的持续集成与云端交付(三)- 从零搭建持续交付系统
查看>>
《算法基础:打开算法之门》一3.4 归并排序
查看>>
高德开放平台开放源代码 鼓励开发者创新
查看>>
《高并发Oracle数据库系统的架构与设计》一2.5 索引维护
查看>>
《Exchange Server 2010 SP1/SP2管理实践》——2.4 部署外部网络环境
查看>>
Firefox 是 Pwn2own 2014 上攻陷次数最多的浏览器
查看>>
阿里感悟(十八)- 应届生Review
查看>>
《计算广告:互联网商业变现的市场与技术》一第一部分 在线广告市场与背景...
查看>>
话说模式匹配(5) for表达式中的模式匹配
查看>>
《锋利的SQL(第2版)》——1.7 常用函数
查看>>
《Arduino家居安全系统构建实战》——1.5 介绍用于机器学习的F
查看>>
jquery中hover()的用法。简单粗暴
查看>>
线程管理(六)等待线程的终结
查看>>
spring boot集成mongodb最简单版
查看>>