热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

solr语法如何在spring中使用

今天就跟大家聊聊有关solr语法如何在spring中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文

今天就跟大家聊聊有关solr语法如何在spring中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

在介绍solr的使用方法之前,我们需要安装solr的服务端集群。基本上就是安装zookeeper,tomcat,jdk,solr,然后按照需要配置三者的配置文件即可。由于本人并没有具体操作过如何进行solr集群的搭建。所以关于如何搭建solr集群,读者可以去网上查看其它资料,有很多可以借鉴。这里只介绍搭建完solr集群之后,我们客户端是如何访问solr集群的。

之前介绍过,spring封装nosql和sql数据库的使用,都是通过xxxTemplate。solr也不例外。

我们需要引入solr的jar包

 
      org.springframework.data 
      spring-data-solr 
      1.0.0.RELEASE 
     

然后引入solr在spring中封装的配置

 
   
   
   
 
 
   
 
 
 
   
 

然后重写我们的SolrServiceImpl就可以了。

但是,本文我们不用spring中封装的xxxTemplate这种格式做讲解。个人在使用spring封装solr的方式的时候遇到了各种各样的问题,可能是能力太low架控不了吧。下面我们主要讲解下如何使用solr的原生api进行访问。

首先:

引入solr的原生代码api的jar包

 
  org.apache.solr 
  solr-solrj 
  4.7.2 
 

其次:

在spring的配置文件中配置我们solr的FactoryBean类,此类是作为我们编写自己业务service类的属性来操作solr。

 
   
   
   
 

solr.zkHost是我们配置的zookeeper集群

orderInfo是我们存储在solr中的数据结构bean

再次:

编写我们的SolrCloudServerFactoryBean类,其中使用了spring的FactoryBean,和InitializingBean。关于这两者的含义读者可以参考其他资料,基本意思是spring容器在注册该bean之前,需要进行的一些初始化操作。通过afterPropertiesSet方法可以看到我们在使用solr之前做的一些初始化操作。

package com.jd.fms.prism.solr.service; 
 
import org.apache.http.client.HttpClient; 
 
/** 
 * solrj spring integration 
 * 
 * @author bjchenrui 
 */ 
public class SolrCloudServerFactoryBean implements FactoryBean, InitializingBean { 
 
  private CloudSolrServer cloudSolrServer; 
 
  private String zkHost; 
 
  private String defaultCollection; 
 
  private int maxCOnnections= 1000; 
 
  private int maxCOnnectionsPerHost= 500; 
 
  private int zkClientTimeout = 10000; 
 
  private int zkCOnnectTimeout= 10000; 
 
  private Lock lock = new ReentrantLock(); 
 
  public SolrServer getObject() throws Exception { 
    return cloudSolrServer; 
  } 
 
  public Class getObjectType() { 
    return SolrServer.class; 
  } 
 
  public boolean isSingleton() { 
    return true; 
  } 
 
  public void afterPropertiesSet() throws Exception { 
    ModifiableSolrParams params = new ModifiableSolrParams(); 
    params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, maxConnections); 
    params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, maxConnectionsPerHost); 
    HttpClient client = HttpClientUtil.createClient(params); 
    LBHttpSolrServer lbServer = new LBHttpSolrServer(client); 
    lock.lock(); 
    try { 
      if(cloudSolrServer == null) { 
        cloudSolrServer = new CloudSolrServer(zkHost, lbServer); 
      } 
    } finally { 
      lock.unlock(); 
    } 
 
    cloudSolrServer.setDefaultCollection(defaultCollection); 
    cloudSolrServer.setZkClientTimeout(zkClientTimeout); 
    cloudSolrServer.setZkConnectTimeout(zkConnectTimeout); 
  } 
 
  public void setCloudSolrServer(CloudSolrServer cloudSolrServer) { 
    this.cloudSolrServer = cloudSolrServer; 
  } 
 
  public void setZkHost(String zkHost) { 
    this.zkHost = zkHost; 
  } 
 
  public void setDefaultCollection(String defaultCollection) { 
    this.defaultCollection = defaultCollection; 
  } 
 
  public void setMaxConnections(int maxConnections) { 
    this.maxCOnnections= maxConnections; 
  } 
 
  public void setMaxConnectionsPerHost(int maxConnectionsPerHost) { 
    this.maxCOnnectionsPerHost= maxConnectionsPerHost; 
  } 
 
  public void setZkClientTimeout(int zkClientTimeout) { 
    this.zkClientTimeout = zkClientTimeout; 
  } 
 
  public void setZkConnectTimeout(int zkConnectTimeout) { 
    this.zkCOnnectTimeout= zkConnectTimeout; 
  } 
 
} 

最后:

现在就可以编写我们的service类了,这里就是我们具体如何操作solr的地方。

package com.jd.fms.prism.solr.service.impl; 
 
import com.jd.fms.prism.common.utils.DateUtil; 
 
@Service("orderInfoSolrService") 
public class OrderInfoNativeSolrServiceImpl { 
   
  private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.FORMATER11); 
  private static SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat(DateUtil.FORMATER4); 
   
  @Resource(name = "orderInfoSolrServer") 
  private SolrServer solrServer; 
 
  /** 
   * 创建索引 
   * 
   * @param orderInfo 
   */ 
  public void creatIndex(OrderInfo orderInfo) throws IOException, SolrServerException { 
    solrServer.addBean(orderInfo); 
    solrServer.commit(); 
  } 
  /** 
   * 查询条件的生成。支持字段的精确查询,模糊查询,范围查询。 
   * @param orderIdfilter 
   * @param queryObj 
   * @param queryTimeList 
   * @param sorts 
   * @return 
   * @throws Exception 
   */ 
  public SolrQuery iniFilter(String orderIdfilter,OrderInfo queryObj,List queryTimeList, Sort... sorts) throws Exception { 
    SolrQuery sQuery = new SolrQuery(); 
    String queryQ = "validTag:1"; 
    sQuery.setQuery(queryQ); 
    StringBuilder filter = new StringBuilder(); 
    if(null != orderIdfilter){ 
      filter.append(orderIdfilter); 
      queryObj.setOrderId(null); 
    } 
    //添加过滤条件 
    Field[] fields = queryObj.getClass().getDeclaredFields(); 
 
    String fieldName = ""; 
    String fieldValue = ""; 
    for (Field field:fields){ 
      if(field.isAnnotationPresent(org.apache.solr.client.solrj.beans.Field.class)){ 
        field.setAccessible(true); 
        fieldName = field.getName(); 
        fieldValue = String.valueOf(field.get(queryObj)); 
        if (null != fieldValue && !"null".equals(fieldValue) && !"".equals(fieldValue) && !"0.0".equals(fieldValue)){ 
          //如果是会员类型,则添加模糊查询 
          if(fieldName.equals("memberId") || fieldName.equals("orderType")){ 
            fieldValue = "*" + fieldValue + "*"; 
          } 
          filter.append(fieldName + ":" + fieldValue).append(" AND "); 
        } 
      } 
    } 
    if(queryTimeList!=null && queryTimeList.size() > 0) { 
      Iterator iterator = queryTimeList.iterator(); 
      while(iterator.hasNext()) { 
        QueryTime queryTime = iterator.next(); 
        String beginDate = simpleDateFormat.format(queryTime.getBeginTime().getTime()); 
        String endDate = simpleDateFormat.format(queryTime.getEndTime().getTime()); 
        filter.append(queryTime.getFieldName() + ":" + "[" + beginDate + " TO " + endDate + "] AND "); 
      } 
    } 
    if(filter.length()>0){ 
      filter.delete(filter.length()-5, filter.length()); 
    } 
    sQuery.addFilterQuery(filter.toString()); 
    if(sQuery.toString().equals("")){ 
      sQuery.setQuery("*:*"); 
    } 
    return sQuery; 
  } 
  /** 
   * 查询代码,可以看到我们可以在solr中做聚合,做排序。而且整个过程都是秒级的。 
   * @param map 
   * @param queryObj 
   * @param queryTimeList 
   * @param page 
   * @param sorts 
   * @return 
   * @throws Exception 
   */ 
  public Page query(Map map,OrderInfo queryObj, List queryTimeList, Pageable page, Sort... sorts) throws Exception { 
    SolrQuery sQuery = iniFilter(null,queryObj,queryTimeList); 
 
    //添加分页 
    if(page != null){ 
      sQuery.setStart(page.getPageNumber()*page.getPageSize()); 
      sQuery.setRows(page.getPageSize()); 
    } 
    //添加排序 
    /*if (null != sorts){ 
      sQuery.setSort("orderId",SolrQuery.ORDER.asc); 
    }*/ 
    QueryResponse respOnse= null; 
    sQuery.setGetFieldStatistics("orderPrice"); 
    sQuery.setGetFieldStatistics("duePrice"); 
    sQuery.setGetFieldStatistics("diffPrice"); 
    try { 
      respOnse= solrServer.query(sQuery); 
    } catch (SolrServerException e) { 
      e.printStackTrace(); 
    } 
    SolrDocumentList list = response.getResults(); 
    Map mapSum = response.getFieldStatsInfo(); 
    String orderPriceSum = null; 
    if(mapSum.get("orderPrice") != null && !mapSum.get("orderPrice").toString().equals("") ){ 
      orderPriceSum = mapSum.get("orderPrice").getSum().toString(); 
    } 
    String duePriceSum = null; 
    if(mapSum.get("duePrice") != null && !mapSum.get("duePrice").toString().equals("") ){ 
      duePriceSum = mapSum.get("duePrice").getSum().toString(); 
    } 
    String diffPriceSum = null; 
    if(mapSum.get("diffPrice") != null && !mapSum.get("diffPrice").toString().equals("") ){ 
      diffPriceSum = mapSum.get("diffPrice").getSum().toString(); 
    } 
    List list1 = new ArrayList(); 
    DocumentObjectBinder binder = new DocumentObjectBinder(); 
    Iterator iterator = list.iterator(); 
    while(iterator.hasNext()){ 
      OrderInfo orderInfo = binder.getBean(OrderInfo.class, (SolrDocument) iterator.next()); 
      list1.add(orderInfo); 
    } 
    map.put("orderPriceSum", orderPriceSum); 
    map.put("duePriceSum", duePriceSum); 
    map.put("diffPriceSum", diffPriceSum); 
    Page pageList = new PageImpl(list1,page,list.getNumFound()); 
    return pageList; 
  }  
  /** 
   * 我们可以按照key值进行主键查询。 
   * @param id 
   * @return 
   * @throws Exception 
   */ 
   
  public List queryByOrderId(String id) throws Exception { 
    SolrQuery sQuery = new SolrQuery(); 
    String filter = "orderId" + ":" + id; 
    sQuery.setQuery(filter); 
    QueryResponse respOnse= null; 
    try { 
      respOnse= solrServer.query(sQuery); 
    } catch (SolrServerException e) { 
      e.printStackTrace(); 
    } 
    SolrDocumentList list = response.getResults(); 
    List list1 = new ArrayList(); 
    DocumentObjectBinder binder = new DocumentObjectBinder(); 
    Iterator iterator = list.iterator(); 
    while(iterator.hasNext()){ 
      OrderInfo orderInfo = binder.getBean(OrderInfo.class, (SolrDocument) iterator.next()); 
      list1.add(orderInfo); 
    } 
    return list1; 
  } 
 
   
  public void deleteAll(OrderInfo orderInfo) throws IOException, SolrServerException { 
    String sQuery = "*:*"; 
    solrServer.deleteByQuery(sQuery); 
  } 
 
   
  public void deleteById(String id) { 
  } 
 
   
  public void createIndexBatch(List orderInfoList) throws IOException, SolrServerException { 
    solrServer.addBeans(orderInfoList); 
    solrServer.commit(); 
 
  } 
 
   
  public void deleteBySolrQuery(String solrQuery) throws IOException, SolrServerException { 
    solrServer.deleteByQuery(solrQuery); 
    solrServer.commit(); 
  } 
 
  public SolrServer getSolrServer() { 
    return solrServer; 
  } 
 
  public void setSolrServer(SolrServer solrServer) { 
    this.solrServer = solrServer; 
  } 
} 

当然solr的api不止于此,我们此处只是罗列了一些比较常用的使用方法。对于solr的查询,有以下几点需要注意。

1.    solr生成查询语句的时候,是有q查询和fq查询之分的。哪些查询条件放在q查询里,哪些查询条件放在fq查询里,对查询的效率还是有较大的影响的。一般固定不变的查询条件放在q查询里,经常变化的查询条件放在fq里。上述代码中validTag:1就放在了q查询里,循环里的字符串filter则放在了我们的fq查询里。

2.    solr查询时,要了解solr服务器集群的配置文件中使用的是什么样的分词器,不同分词器对模糊查询的结果是有影响的。比如常见的IK分词器和标准分词器(如果我们有一个字段的名称为:我是中国人,ik分词器在solr里的存储就成为了“我”,“中国人”,“中国”,“国人”。而标准分词器则会存储为“我”,“是”,“中”,“国”,“人”。如果我们使用全称查询,即查询:我是中国人,两者是没有问题的。但是使用模糊查询,比如查询“*我是*”,则两个分词器分词都查不出来结果,而如果我们的查询条件是“*中国人*”则在ik分词器下可以查询出结果,在标准分词器下查不出结果。)

3.    使用solr的过程中,需要定时执行solr的optimize函数来清理磁盘碎片,否则会影响读写效率。对于optimize的参数建议为(false,false,5)。

4.    写solr数据的时候,尽量使用createIndexBatch方法,这是因为solr在执行写入的时候,写入一条数据和写入多条数据都需要全量建索引,其执行时间是差不多的。

看完上述内容,你们对solr语法如何在spring中使用有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程笔记行业资讯频道,感谢大家的支持。


推荐阅读
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
  • 使用freemaker生成Java代码的步骤及示例代码
    本文介绍了使用freemaker这个jar包生成Java代码的步骤,通过提前编辑好的模板,可以避免写重复代码。首先需要在springboot的pom.xml文件中加入freemaker的依赖包。然后编写模板,定义要生成的Java类的属性和方法。最后编写生成代码的类,通过加载模板文件和数据模型,生成Java代码文件。本文提供了示例代码,并展示了文件目录结构。 ... [详细]
  • Struts2+Sring+Hibernate简单配置
    2019独角兽企业重金招聘Python工程师标准Struts2SpringHibernate搭建全解!Struts2SpringHibernate是J2EE的最 ... [详细]
  • 本文介绍了关于apache、phpmyadmin、mysql、php、emacs、path等知识点,以及如何搭建php环境。文章提供了详细的安装步骤和所需软件列表,希望能帮助读者解决与LAMP相关的技术问题。 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • Vagrant虚拟化工具的安装和使用教程
    本文介绍了Vagrant虚拟化工具的安装和使用教程。首先介绍了安装virtualBox和Vagrant的步骤。然后详细说明了Vagrant的安装和使用方法,包括如何检查安装是否成功。最后介绍了下载虚拟机镜像的步骤,以及Vagrant镜像网站的相关信息。 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • 本文介绍了在sqoop1.4.*版本中,如何实现自定义分隔符的方法及步骤。通过修改sqoop生成的java文件,并重新编译,可以满足实际开发中对分隔符的需求。具体步骤包括修改java文件中的一行代码,重新编译所需的hadoop包等。详细步骤和编译方法在本文中都有详细说明。 ... [详细]
  • Tomcat安装与配置教程及常见问题解决方法
    本文介绍了Tomcat的安装与配置教程,包括jdk版本的选择、域名解析、war文件的部署和访问、常见问题的解决方法等。其中涉及到的问题包括403问题、数据库连接问题、1130错误、2003错误、Java Runtime版本不兼容问题以及502错误等。最后还提到了项目的前后端连接代码的配置。通过本文的指导,读者可以顺利完成Tomcat的安装与配置,并解决常见的问题。 ... [详细]
  • Hadoop2.6.0 + 云centos +伪分布式只谈部署
    3.0.3玩不好,现将2.6.0tar.gz上传到usr,chmod-Rhadoop:hadophadoop-2.6.0,rm掉3.0.32.在etcp ... [详细]
author-avatar
吟伶逸慧喜靖
这个家伙很懒,什么也没留下!