美文网首页
搜索引擎 ~ Solr & SpringDataSolr

搜索引擎 ~ Solr & SpringDataSolr

作者: 帅可儿妞 | 来源:发表于2018-11-10 14:30 被阅读25次

    如果你的项目中用到了搜索,现在的选择就奔上就是Solr或者Elasticsearch了,今天我们就来看看Solr,当然我一般是不会在博客中讲什么原理的,因为讲原理是我自己的理解,我怕误导大家,好了开始吧

    一、简介

    1. 为什么要使用搜索呢?
      • 我们知道,一个大型网站,用户的搜索是一个及其消耗服务器性能的事情,如果在这点上处理不好,将会使得用户体验度大打折扣,甚至拖垮整个应用!
    2. Solr
      • 讲到Solr其实肯定就会提到Lucene,两者的区别在于Lucene是一个底层的API实现,而Solr是在应用的层面上封装了Lucene。
      • Solr是Apache旗下的一款快速的,高度可扩展,可提供高性能,以文本为中心的开源搜索服务器。它基于HTTP请求访问,也就是说跨平台性得到了保障;主要用于构建搜索应用程序。Yonik Seely于2004年创建,并于2006年1月成为Apache软件基金会下的一个开源项目;
      • Solr的另一大可以说是特性就是可以和Hadoop一起使用,也就是说不仅限于搜索,Solr也可以用于数据的存储和数据处理,是一种非关系数据存储和处理技术;
    3. 如果你想知道Elasticsearch和Solr的区别,可以查看这篇

    二、Solr的安装

    1. 在Win上的安装

      • 下载Solr,常用版本你可以去国内的镜像源下载
      • 如果你下载的是Solr5之前的版本,那就需要把安装包下的solr.war复制到Tomcat中,而如果是5及其以后版本则直接运行,即独立部署,两者版本区别请查看这里;独立部署的文章也是一大堆,问度娘;
    2. Solr5之前的版本安装

      • 这里我选择的是4.9.1,即5之前的最后一个版本;
      • 解压之后把dist之中的solr-4.9.1.war复制到Tomcat的webapp下;
      • 启动,等待解压,完成后把下载包中的\example\lib\ext中所有的jar拷贝到Tomcat\webapps\solr\WEB-INF\lib中,主要是给solr提供一个日志方面的包;
      • 配置索引库:把解压包中的\example\solr到电脑中的一个位置,如我放在D:\Documents\SolrHome,我把solr重命名为SolrHome,把D:\Documents\SolrHome配置到Solr应用的web.xml中的env-entity中;
      • 启动Tomcat,访问:http://localhost:8080/solr,安装完成
    3. Solr5及其之后的版本安装

      • // TODO 有时间补

    三、配置中文分词器

    1. 这里我们使用IKAnalyzer来做中文分词,单独使用请参考我的另一片文章中文分词器 ~ IK Analyzer
    2. 在Solr中使用的步骤如下:
      • 文章中文分词器 ~ IK Analyzer中的配置;
      • 修改 SolrHome 中的 schema.xml 文件,配置一个 FieldType,使Solr采用 IKAnalyzer作为默认的文本分词器:
        <fieldType name="text_ik" class="solr.TextField">
            <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
        </fieldType>
        
      • 配置完成后启动服务器

    四、域

    1. 域,即字段,在Solr的配置schema.xml文件中对应的标签是field;还有一个就是fieldType,这个指的是域的数据类型;
    2. 我们一般是要在数据库中搜索数据的,尽管Solr的配置中已经为我们提供了相当多的域,但是我们在做项目的时候还是要根据我们的需求自定义添加一些域,并给这些域设置相应的属性,常见的属性如下:
      • name:指定域的名称,自定义,一般是数据表中的字段名
      • type:指定域的类型,即fieldType
      • indexed:是否索引,取值true/false
      • stored:是否存储,取值true/false
      • required:是否必须,取值true/false
      • multiValued:是否多值,取值true/false
    3. 自定义域
      • 分析需要搜索的字段;
      • 在SolrHome的schema.xml文件中添加字段field,根据业务需求添加这些域,同时设置上面的属性;
    4. 复制域
      • 我们在搜索的时候摁钉还会遇到一种情况,用户在搜索的时候可以填写很多信息,而这些信息对应数据库的很多字段,难道我们要把分词的结果全部在数据库中笛卡尔积式 'LIKE' 吗?Solr中为我们解决了这个问题,解决的途径就是使用复制域来解决;
      • 复制域schema.xml文件中对应的标签是copyField,含有两个属性:
        • source:来源域的name属性
        • dest:目标域,即:将source域复制到该目标域进行搜索)
    5. 动态域
      • 动态域主要用来解决项目表中存储的数据是是动态类型的情况,比如我们常用的字典表就是这一类型,某列的值是根据当前记录的类型决定的;
      • 动态域的配置与普通的字段域大部分相同,为疑似不同的就是在name属性上提供通配符 *;

    五、SolrJ

    1. SolrJ是Solr官方提供的Java客户端,它提供了增删改查Solr索引的Java接口。SolrJ针对Solr提供了Rest 的HTTP接口进行了封装, SolrJ底层是通过使用httpClient中的方法来完成Solr的操作的;
    2. Solr是一个应用,SolrJ是一个请求Solr应用的客户端,之间使用HTTP进行通讯;
    3. 使用参考这篇文章

    六、SpringDataSolr

    1. SpringDataSolr其实就是Spring对SolrJ的一个封装;
    2. 使用步骤
      • 引入Maven库
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-solr</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>
        
      • 添加配置文件:application-solr.xml
        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="https://www.springframework.org/schema/beans" 
                xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" 
                xsi:schemalocation="https://www.springframework.org/schema/beans
                    https://www.springframework.org/schema/beans/spring-beans.xsd">
                 
            <!-- Solr Server配置方式1  -->
            <solr:solr-server id = "solrServer" url = "<solr-access-url>" />
            
            <!-- Solr Server配置方式2 -->
            <bean id = "solrServer" class = "org.apache.solr.client.solrj.impl.HttpSolrServer">
                <constructor-arg index="0" value = "<solr-access-url>" />
            </bean>
        
            <!-- Solr Server集群配置方式 -->
            <bean id = "solrServer" class = "org.apache.solr.client.solrj.impl.CloudSolrServer">
                <constructor-arg index="0" value="<ip-port-comma>" />
                <property name="defaultCollection" value="<collection-name>" />
            </bean>
            
            <!-- Solr Template -->
            <bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
                <constructor-arg ref="solrServer" />
            </bean>
         
        </beans>
        
      • 关联数据库字段与Solr搜索字段
        • 关联直接使用注解@org.apache.solr.client.solrj.beans.Field作用在实体类上即可,如果数据库字段名和Solr搜索字段不相同则在参数中执行即可;
        • 动态域在关联实体类的时候需要添加注解@Dynamic,凡是需要关联的实体字段是使用@Field,注解@Field是SolrJ提供的,而@Dynamic是SpringDataSolr提供的,所以在pom引用的时候直接引用SpringDataSolr即可,底层的框架会自动引入;
      • 编码初始化Solr数据
        • 编码的时候直接使用solrTemplate的save/delete/deleteById/queryForPage/getById等方法即可实现数据的增删改查,但是要注意的是,增删改语句后必须添加事务的提交语句solrTemplate.commit();,否则数据不会受影响的;
        • 具体的请查看API提示即可;
        • Query:分页查询的封装类,请看代码:
          Query query = new Query("*:*");
          query.setOffset(<start>);
          query.setRows(<page-size>);
          query.setCriteria(<criteria>); // 封装查询条件
          ScoredPage page = solrTemplate.queryForPage(query, <Bean>.class);
          List<<bean>> beansOfThisPage = page.getContent();
          System.out.println("一页数据:" + beansOfThisPage);
          System.out.println("总条数:" + page.getTotalElements());
          System.out.println("总页数:" + page.getTotalPages());
          System.out.println("总页数:" + page.getSize());
          
        • 使用上面的方法结合MyBatis把数据库中的数据保存到Solr索引中;具体就不在赘述;
    3. 关键字搜索
      • 根据上面SolrTemplate的查询方法编写查询Solr的服务;
    4. Solr增量更新(参考这里这里)
      • 我们可以手动编写导入代码结合定时器完成,但是SpringDataSolr已经帮我们做了一部分工作,配置一下即可;如下:
      • 导入solr数据更新的pom:
        <dependency>
            <groupId>org.apache.solr</groupId>
            <artifactId>solr-dataimporthandler</artifactId>
            <version>6.6.5</version>
        </dependency>
        
      • 在SolrHome目录下新建一个文件夹conf,再在conf文件夹下新建dataimport.properties文件,其内容为:
        #################################################  
        #                                               #  
        #       dataimport scheduler properties         #  
        #                                               #  
        #################################################  
                 
        #  to sync or not to sync  
        #  1 - active; anything else - inactive  
        syncEnabled=1
        #  which cores to schedule  
        #  in a multi-core environment you can decide which cores you want syncronized  
        #  leave empty or comment it out if using single-core deployment  
        syncCores=test,hotel
        #  solr server name or IP address  
        #  [defaults to localhost if empty]  
        server=localhost
        #  solr server port  
        #  [defaults to 80 if empty]  
        port=8083
        #  application name/context  
        #  [defaults to current ServletContextListener's context (app) name]  
        webapp=solr
        #  增量索引的参数   
        #  URL params [mandatory]  
        #  remainder of URL  
        params=/dataimport?command=delta-import&clean=false&commit=true
        #  重做增量索引的时间间隔  
        #  schedule interval  
        #  number of minutes between two runs  
        #  [defaults to 30 if empty]  
        interval=1
        #  重做全量索引的时间间隔,单位分钟,默认7200,即5天;  
        #  为空,为0,或者注释掉:表示永不重做索引  
        #reBuildIndexInterval=7200
        #  重做索引的参数  
        reBuildIndexParams=/dataimport?command=full-import&clean=true&commit=true
        #  重做索引时间间隔的计时开始时间,第一次真正执行的时间=reBuildIndexBeginTime+reBuildIndexInterval*60*1000;  
        #  两种格式:2012-04-11 03:10:00 或者  03:10:00,后一种会自动补全日期部分为服务启动时的日期  
        reBuildIndexBeginTime=03:10:00
        
      • 增加增量更新监听器。即在Solr服务的web.xml加入监听器:
        <listener>
            <listener-class>
                org.apache.solr.handler.dataimport.scheduler.ApplicationListener
            </listener-class>
        </listener>
        
      • 编写增量更新SQL:在Solr的conf\data-config.xml中<entity>标签加入两个属性:
        deltaImportQuery="<data-query-sql>'"
        deltaQuery="<primary-key-query-sql>"
        
        • 属性介绍:
          query是获取全部数据的SQL
          deltaImportQuery是获取增量数据时使用的SQL
          deltaQuery是获取主键的SQL
          parentDeltaQuery是获取父Entity的主键的SQL
        • Full Import工作原理:
          1. 执行本Entity的Query,获取所有数据;
          2. 针对每个行数据Row,获取主键,组装子Entity的Query;
          3. 执行子Entity的Query,获取子Entity的数据。
        • Delta Import工作原理:
          1. 查找子Entity,直到没有为止;
          2. 执行Entity的deltaQuery,获取变化数据的主键;
          3. 合并子Entity parentDeltaQuery得到的主键;
          4. 针对每一个主键 Row,组装父Entity的parentDeltaQuery;
          5. 执行parentDeltaQuery,获取父Entity的主键;
          6. 执行deltaImportQuery,获取自身的数据;
          7. 如果没有deltaImportQuery,就组装Query;
        • 限制:
          ✔ 子Entity的query必须引用父Entity的主键;
          ✔ 子Entity的parentDeltaQuery必须引用自己的主键;
          ✔ 子Entity的parentDeltaQuery必须返回父Entity的主键;
          ✔ deltaImportQuery引用的必须是自己的主键;

    相关文章

      网友评论

          本文标题:搜索引擎 ~ Solr & SpringDataSolr

          本文链接:https://www.haomeiwen.com/subject/gojzxqtx.html