[FRAME]搜索引擎 ~ Solr & SpringDataSolr

如果你的项目中用到了搜索,现在的选择就奔上就是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引用的必须是自己的主键;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容

  • 一.简介 Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通...
    泰安青年阅读 3,663评论 0 37
  • Solr的安装与配置 多数搜索引擎应用都必须具有某种搜索功能,而搜索功能往往大量的消耗资源导致应用程序运行缓慢。为...
    TyCoding阅读 5,251评论 1 5
  • 1 什么是Solr2 Solr和lucene区别3 Solr的安装及配置、相关文件说明 1 什么是Solr Sol...
    艾剪疏阅读 1,124评论 0 1
  • 1 准备工作及相关介绍 solr和lucene的版本是同步更新的,最新版本是6.5.0。本案例使用4.10.3 j...
    阿太哥阅读 2,329评论 1 5
  • 1. 什么是solr    Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的...
    东方舵手阅读 940评论 1 5