solr的使用以及配置

使用搜索引擎的好处

  • 传统的SQL语句实现方式效率低下

搜索引擎运行原理

 

solr简介

  • 基于Lucene的Java搜索引擎服务器程序
  • 功能
    • 数据导入
    • 增量更新
    • 数据检索(全文检索,高亮显示,精确搜索)
  • Solr下载地址
  • http://archive.apache.org/dist/lucene/solr/
  • 教学版本
    • Solr4.9.1
  • Solr4.9.1依赖环境
    • JDK1.7+
    • Tomcat7.0+

solr安装配置

  • solr_home:管理Core的配置目录
  • core(collection):类似于数据库中的视图,一个core代表一种类型的数据集合

初始配置

  1. 将dist\solr-4.9.war文件复制到tomcat的webapps目录下,并将文件命名为solr.war
  2. 复制 solr解压包下example\lib\ext 下所有的jar 到tomcat 的lib目录下
  3. 在计算机本地新建一个文件夹solrhome(当然你可以随便起名字), 然后复制solr-4.9.1\example\solr 下的所有文件到solrhome下
  4. 启动tomcat,待tomcat启动成功后,关闭tomcat。打开tomcat的webapps目录。注意,此时solr的war包以及被解压成solr文件夹。删除tomcat的webapps目录下的solr的war包,保留solr文件夹
  5. 修改配置文件 apache-tomcat-7.0.67\webapps\solr\WEB-INF\web.xml

<env-entry>
    <env-entry-name>solr/home</env-entry-name>
    <env-entry-value>D:/solr/solr_home</env-entry-value>
    <env-entry-type>java.lang.String</env-entry-type>
</env-entry>

  • 看到如下界面说明初始配置成功

core操作

  • 新建core
    1. 新建core(solr中把配置的每一个模块都叫core),在solr_home目录下,拷贝collection1文件夹,并起名为test。打开test文件夹,修改core.properties文件,将name修改为test
    2. 重新启动tomcat,并访问solr,如出现以下界面,则表示新建test core新建成功

  • 删除core
    • 删除solr_home下test文件夹即可

导入数据

  • 拷贝数据库连接jar包(mysql-connector-java-5.1.18.jar)到tomcat的lib目录
  • 配置数据源
  • 配置字段
  • 执行数据导入
  • 测试数据导入结果
  • 详细步骤
  1. 拷贝数据库连接jar包(mysql-connector-java-5.18.jar)到tomcat的lib目录
  2. 以创建testcore的方式新建hotel core
  3. 打开hotel的conf文件夹中的solrconfig.xml文件,在requestHandlername="/select"
  1. 前面上加上一个dataimport的处理的Handler

<requestHandler name="/dataimport"
                class="org.apache.solr.handler.dataimport.DataImportHandler">
    <lst name="defaults">
        <str name="config">data-config.xml</str>
    </lst>
</requestHandler>

  1. 在hotel的的conf文件夹下并新建data-config.xml文件,配置如下

<?xml version="1.0" encoding="UTF-8"?>
<dataConfig>
    <dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver"
    url="jdbc:mysql://127.0.0.1:3306/itripdb" user="root" password="root" />
    <document name="hotel_doc">
       <entity name="hotel" pk="id" query="select id,hotelName,address from itrip_hotel">
           <field column="id" name="id"/>
           <field column="hotelName" name="hotelName"/>
           <field column="address" name="address"/>
       </entity>
    </document>
</dataConfig>

  • dataSource是数据库数据源。
  • Entity就是一张表对应的实体,pk是主键,query是查询语句。
  • Field对应一个字段,column是数据库里的column名,后面的name属性对应着Solr的Filed的名字。
  1. 修改同目录下的schema.xml(schema.xml是solr对数据库里的数据进行索引管理和数据字段展示管理的配置文件)
    • 删除多余的field,保留version 和text这两个field(注意不要删除fieldType)
  2. 添加索引字段:这里每个field的name要和data-config.xml里的entity的field的name一样,一一对应

<field name="id" type="int" indexed="true" stored="true"/>
<field name="hotelName" type="string" indexed="true" stored="true"/>
<field name="address" type="string" indexed="true" stored="true"/>

  1. 将导入数据的JAR包拷贝到webapps/solr的lib目录下
    • solr-4.9.1\dist\solr-dataimporthandler-4.9.1.jar
    • solr-4.9.1\dist\solr-dataimporthandler-extras-4.9.1.jar
  2. 启动Tomcat,执行数据导入
    • 异常处理
    • 当你把id设置为int后,solr在启动的时候会加载elevate.xml,这个文件中定义的id的值为MA147LL/A,那么就出现异常Invalid Number: MA147LL/A
    • 解决办法,将elevate.xml文件中这段代码注释掉

 

  1. 查询数据

实现增量更新

  • 增量更新:根据某一字段的值,动态导入更新数据。
  • 配置增量更新
    • 导入增量更新jar包
    • 配置增量更新文件
    • 增加增量更新监听器
    • 编写增量更新SQL
  • 启动测试
  • 详细步骤
  1. 将资料中提供的apache-solr-dataimports-cheduler.jar包添加至solr的lib目录下
    • 使用教学提供的jar包
  2. 增加增量更新配置文件,在solr_home文件夹下新建conf文件夹,并新建名为dataimport.properties的配置文件

# dataimportschedulerproperties #
# #
#################################################
# tosyncornottosync
# 1-active;anythingelse-inactive
syncEnabled=1
# whichcorestoschedule
# inamulti-coreenvironmentyoucandecidewhichcoresyouwantsyncronized
# leaveemptyorcommentitoutifusingsingle-coredeployment
syncCores=hotel
# solrservernameorIPaddress
# [defaultstolocalhostifempty]
server=localhost
# solrserverport
# [defaultsto80ifempty]
port=8080
# applicationname/context
# [defaultstocurrentServletContextListener'scontext(app)name]
webapp=solr
# 增量索引的参数
# URLparams[mandatory]
# remainderofURL
params=/dataimport?command=delta-import&clean=false&commit=true
# 重做增量索引的时间间隔
# scheduleinterval
# numberofminutesbetweentworuns
# [defaultsto30ifempty]
interval=1
# 重做全量索引的时间间隔,单位分钟,默认7200,即5天;
# 为空,为0,或者注释掉:表示永不重做索引
#reBuildIndexInterval=7200
# 重做索引的参数
reBuildIndexParams=/dataimport?command=full-import&clean=true&commit=true
# 重做索引时间间隔的计时开始时间,第一次真正执行的时间
reBuildIndexBeginTime+reBuildIndexInterval*60*1000;
# 两种格式:2012-04-1103:10:00 或者 03:10:00,后一种会自动补全日期部分为服务启动时的
日期
reBuildIndexBeginTime=03:10:00

  1. 新增增量更新数据的监听器,在solr的web.xml中加入以下监听器

<listener>
    <listener-class>
        org.apache.solr.handler.dataimport.scheduler.ApplicationListener
    </listener-class>
</listener>

  1. 修改导入数据查询SQL(solr_home\hotel\conf\data-config.xml)

deltaImportQuery="select id,hotelName,address from itrip_hotel where id = '${dih.delta.id}'"
 
deltaQuery="SELECT id as id FROM itrip_hotel where modifyDate > '${dih.last_index_time}'"  

  • deltaQuery是根据dataimport.properties配置文件中的更新时间,从数据库中查询出,修改日期在最后一次更新日期之后的酒店数据,并记录其id,而deltaImportQuery的目的是将deltaQuery查询出的数据导入到solr中
  1. 启动Tomcat进行测试
    • 修改数据库中的酒店数据并同时修改该数据的modifyDate时间
    • 1分钟后查询酒店数据,确定数据是否更新

全文检索

  • 全文检索:分析用户输入,并对用户输入进行拆分,组合等转化操作,根据转化后的数据对数据源数据进行检索,并将检索结果返回给用户
  • 分词器:将用户输入根据语义拆分成多个词语
    • 常见的中文分词器
      • word分词器
      • Ansj分词器
      • IKAnalyzer分词器
      • 课程选用分词器:IKAnalyzer分词器(版本2012FF_ul.jar)
  • Solr分词器配置
    • 首先,下载IKAnalyzer
      • https://github.com/medcl/elasticsearch-analysis-ik
    • 拷贝jar包
    • 配置过滤词语stopword.dic
    • 配置分词器
      • 配置schema.xml
      • 修改字段类型
    • 重启Tomcat,访问Solr测试分词器
  • 详细步骤
  1. 将ik的所有jar文件 拷贝到 webapps\solr\WEB-INF\lib 目录下
  2. 在webapps\solr\WEB-INF\下新建classes文件夹,将IKAnalyzer.cfg.xml和stopword.dic文件拷贝到改文件夹下
  3. 在 solr_home\hotel\conf\schema.xml 增加如下配置

<fieldType name="text_ik" class="solr.TextField">
    <analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
    <analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

  1. 修改solrhome\hotel\conf\schema.xml将hotelName和address指定成为textik类型

<field name="hotelName" type="text_ik" indexed="true" stored="true"/>
<field name="address" type="text_ik" indexed="true" stored="true"/>

  1. 重启tomcat测试

 

solr查询语法

  • q – 查询字符串,一般用于关键词过滤
    • hotelName:北京
  • fl – (field list)指定返回字段
    • id,hotelName
  • start –偏移值
    • 从第几条开始
  • rows – 指定返回结果最多有多少条记录,配合start来实现分页
    • 每页显示条数
  • sort – 排序
    • id asc/desc
  • wt – (writer type)指定输出格式(xml, json, python,ruby,php,csv)
  • fq – (filter query)过滤查询
    • 作用:在q查询符合结果中同时是fq查询符合的
    • 执行完成之后,会对结果进行缓存 id:3 or id:5id:3 and hotelName:玉

solr多字段匹配

  • 需求
    • 对多个字段进行检索
  • 步骤
    • 新建field指定multiValued="true”
    • 配置copyField
  • 详细步骤
  1. 在hotel/conf/schema.xml文件中新增filed字段存储多字段的值
  2. 添加如下内容

<field name="keyword" type="text_ik" indexed="true" stored="true" multiValued="true"/>
<copyField source="hotelName" dest="keyword"/>
<copyField source="address" dest="keyword"/>

solrj集成solr应用

  • solr本身提供了对外调用的Http接口,利用Http请求可以直接从solr中获取数据。为了方便Java程序员调用solr,Apache提供了基于solr操作的solrj程序包。
  • 创建Solr查询的接收对象
  • 编写客户端程序
  • 创建HttpSolrClient对象
  • 创建SolrQuery对象
  • 创建QueryResponse数据接收对象
  • 接收数据,转化数据
  • 测试
  • 详细步骤
  1. 下载solrj程序jar包
  2. 使用maven依赖方式添加

<dependency>
    <groupId>org.apache.solr</groupId>
    <artifactId>solr-solrj</artifactId>
    <version>5.3.1</version>
</dependency>
<!--solrj的两个依赖jar包,是日志框架相关的jar包 -->
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>

  1. 在程序中创建solr查询的接收对象
    • 对应schema文件-创建Solr查询的接收对象
    • 添加Field注解

public class ItripHotelVO implements Serializable {
    @Field
    private Integer id;
    @Field
    private String hotelName;
    @Field
    private String address;
}

 

  1. 编写客户端程序
    1. 创建HttpSolrClient对象
    2. 创建SolrQuery对象
    3. 创建QueryResponse数据接收对象
    4. 接收数据,转化数据

@Test
public void test1() {
    // 连接url---本地solr访问地址:ip:端口号/solr/模块名
    String url = "http://localhost:8080/solr/hotel";
    // 创建solrClient
    HttpSolrClient solrClient = new HttpSolrClient(url);
    // 设置响应的解析器
    solrClient.setParser(new XMLResponseParser());
    // 设置建立连接的最长时间
    solrClient.setConnectionTimeout(5000);

    // 定义查询对象solrQuery
    SolrQuery solrQuery = new SolrQuery("*:*");
    // 设置排序规则
    solrQuery.setSort("id", SolrQuery.ORDER.asc);
    // 设置起始位置
    solrQuery.setStart(0);
    solrQuery.setRows(10);

    try {
        // 得到查询的响应对象
        QueryResponse queryResponse = solrClient.query(solrQuery);
        // 通过getBeans可以执行查询,将solr中的数据通过.class反射封装到对象中
        List<ItripHotelVO> list = queryResponse.getBeans(ItripHotelVO.class);
        for (ItripHotelVO hotelVO : list) {
            System.out.println(hotelVO.getHotelName());
        }
    } catch (SolrServerException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

dao的封装

  • 出口
    • controller JSON
  • 分层
    • 数据访问层
      • 通用查询抽取
      • 参数抽取
  • 业务逻辑层
  • 表示层
  • 抽取baseDao

public class BaseDao<T> {

    private HttpSolrClient solrClient;
    private QueryResponse queryResponse;

    public BaseDao(String url) {
        // 创建solrClient
        solrClient = new HttpSolrClient(url);
        // 设置响应的解析器
        solrClient.setParser(new XMLResponseParser());
        // 设置建立连接的最长时间
        solrClient.setConnectionTimeout(5000);
    }

    public List<T> queryList(SolrQuery solrQuery, Class clazz) {
        List<T> list = new ArrayList<>();
        try {
            // 得到查询的响应对象
            queryResponse = solrClient.query(solrQuery);
            // 通过getBeans可以执行查询,将solr中的数据通过.class反射封装到对象中
            list = queryResponse.getBeans(clazz);
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return list;
        }
    }

}

  • 编写具体HotelDao

public class HotelDao extends BaseDao {

    private static String url = "http://localhost:8080/solr/hotel";

    public HotelDao() {
        // 注意,url属性前一定要用static修饰,否则会报错
        super(url);
    }

    public List<ItripHotelVO> queryList(String keyword) {
        SolrQuery solrQuery = new SolrQuery("keyword:" + keyword);
        // 调用baseDao的queryList方法
        List list = this.queryList(solrQuery, ItripHotelVO.class);
        return list;
    }
}

猜你喜欢

转载自blog.csdn.net/GoldWashing/article/details/81501908