solr简单入门

在web开发的时候, 通常, 我们在从数据库中取出数据然后展示在页面上, 但是, 查询数据库属于耗时操作, 这种方式的效率极低, 只适用于用户访问量比较小的情况. 如果出现像淘宝,天猫618节那样用户并发访问量急剧增长的情况. 仅仅只是通过从数据库中查出数据, 已经远远满足不了用户的需求了. 所以, 我们需要建立索引来提高用户的访问速度, 而不是每个操作都需要操作数据库, 这就需要用到我接下来要讲到的全文检索技术 solr.

  • 第一步, 先确定是否配置好java环境, 如果没有, 请先配置好

  • 第二步, 下载tomcat, 并安装

  • 第三步, 下载solr:
    解压到当前目录, 目录结构如下:

    进入dist目录,将solr-4.10.3.war复制到tomcat的webapps目录下, 并重命名为solr.war
    cp solr-4.10.3.war /usr/local/tomcat/webapps/solr.war

    启动tomcat后, 该目录下会自动将solr.war解压, 生成solr文件夹, 进入到该文件夹, cd solr/WEB-INF/, 我们将下载的solr-4.10.3该目录下 solr-4.10.3/example/lib/ext下所有的jar包复制到WEB-INF/lib目录下,
    并在WEB-INF的目录下创建classes文件夹,


下载solr中文分词器 IK Analyzer 2012FF_hf1.
解压后, 将IK Analyzer 2012FF_hf1目录下的IKAnalyzer2012FF_u1.jar复制到WEB-INF/lib目录下, 将ext.dic, IKAnalyzer.cfg.xml, stopword.dic复制到刚创建的WEB-INF/classes目录下.

  • 进入到solr目录下的example目录, 复制solr目录到~/下, 并重命名为solrhome
    cp -r solr ~/solrhome

    solrhome目录下有个collection1目录, 这就是我们项目所需要配置的目录.
    之后我们来修改solr/WEB-INF/web.xml, 修改如下
    <env-entry>
       <env-entry-name>solr/home</env-entry-name>
       <env-entry-value>/home/dagger/solrhome</env-entry-value>
       <env-entry-type>java.lang.String</env-entry-type>
    </env-entry>

~/solrhome就是/home/dagger/solrhome目录这时候, 我们的solrhome目录就已经指定好了, solrhome目录.

就是我们solr的家目录,
其中的collection1就相当与一个项目工程, 如果想要新加一个collection, 我们只需将collection1复制一份到当前目录并重命名为collection2.
修改collection1/conf/schema.xml, 如果我们要用刚刚配置的中文分词器的话, 我们需要在该配置文件做下配置,
在根节点下配置如下

    <!-- 中文分词器 -->
  <fieldType name="text_ik" class="solr.TextField">
    <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  </fieldType>

重启tomcat后配置生效
访问solr项目: localhost:8080/solr

访问页面如图:

我们在左侧边栏的下拉列表core selector选中collection1, 这就是~/solrhome/collection1, 随后再选中Analysis, 我们从网上随便找一段话, 来试试中文分词的效果:


我们将语句放入Field Value (Index)文本框中, 在Analyse Fieldname / FieldType上选中 text_ik (这是我们在~/solrhome/collection/conf/schema.xml)中配置中文分词器fieldType标签上的name属性值,
随后, 我们点击Analyse Values蓝色按钮, 进行分词. 效果如下, 感觉还不错.

  • 接下来, 我们需要将数据库中的数据导入到solr中的collection1中
    请先准备3个jar包

    mysql驱动包
    dataimport

将这3个jar包放到solr/WEB-INF/lib目录下, 进入到~/solrhome/collection1, 修改solrconfig.xml, 添加以下配置

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

再在当前目录创建data-config.xml, 配置如下:
userpassword根据自己的mysql用户名和密码做配置
url后写上自己的数据库名称
entity的name属性写上自己的表名称, query为sql查询语句, 查询出来的字段要对应 schema.xml中配置的field标签中的name, 你也可以在schema.xml中自定义field.
field 的column属性为表中的字段民, name属性对应schema.xml中的field标签的配置

<?xml version="1.0" encoding="UTF-8" ?>  
<dataConfig>   
    <dataSource type="JdbcDataSource"   
              driver="com.mysql.jdbc.Driver"   
              url="jdbc:mysql://localhost:3306/boot_crm"   
              user=""   
              password=""/>   
    <document>   
        <entity name="customer" query="SELECT cust_id, cust_name, cust_source, cust_industry FROM customer">
             <field column="cust_id" name="cust_id"/> 
             <field column="cust_name" name="cust_name"/> 
             <field column="cust_source" name="cust_source"/> 
             <field column="cust_industry" name="cust_industry"/> 
        </entity>   
    </document>   
</dataConfig>

schema.xml中对应customer表字段的配置

  • type代表字段的类型, 如果type指定为text_ik, 那么表示solr按照这个字段进行分词,indexed表示是否为这个字段创建索引, sotred表示是否在solr查询的结果中显示这个字段
   <!-- 中文分词器 -->
  <fieldType name="text_ik" class="solr.TextField">
    <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  </fieldType>
  <!-- customer表中对应的字段 -->
  <field name="cust_name" type="text_ik" indexed="true" stored="true"/>
  <field name="cust_source" type="string" indexed="true" stored="true"/>
  <field name="cust_industry" type="string" indexed="true" stored="true"/>

修改uniqueKey标签, 找到原来name为id的field标签, 修改如下

<!-- <uniqueKey>id</uniqueKey> -->
<uniqueKey>cust_id</uniqueKey>
...

<!-- <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" /> -->
<field name="cust_id" type="int" indexed="true" stored="true" required="true" multiValued="false" />

solr默认主键类型为string类型, 如果你的主键的类型为int或其它类型, 那么你需要修改solrconfig.xml配置文件, 将以下代码注释掉

   <!-- 解决id非string类型报错的问题 -->
    <!-- 
  <searchComponent name="elevator" class="solr.QueryElevationComponent" >
    <str name="queryFieldType">string</str>
    <str name="config-file">elevate.xml</str>
  </searchComponent>
  -->

重起tomcat使配置生效


在Dataimport选项卡中, 确认Command为full-import, 点击Execute, 开始导入数据, 我们需要一直点击Refresh Status, 确认有成功信息为止, 表示customer表中的数据导入成功. 在Query选项卡中, 点击Execute Query, 右边就会有数据产生.

这时候, 我们就可以通过访问http://localhost:8080/solr/这个接口, 来获取数据库中的数据了, 而不需要再次从数据库中查找
我先来介绍, 如何在这个图形界面操作数据:
在Documents选项卡, 将Document Type选为xml格式,

  • 根据cust_id删除索引

    这时候, cust_id为17的数据就被删掉了, 这里的id指的就是cust_id, 不管你主键叫什么名字, 等价于id
  • 添加新索引, 将Document Type选为JSON格式,在添加的时候我们就不能使用id了, 必须指定cust_id

    对于索引的操作, 我们经常用的最多的是查询操作, 所以接下来, 我将会话很多的时间讲一下, solr查询的操作  

进入Query选项卡

  • q: 查询字符串, 必须有, 如果查询所有时使用:, 例如, cust_name为张三的数据:

    cust_name:张三

  • fq: 过滤查询, 在q的查询结果中使用fq过滤符合条件的数据, 例如, 筛选cust_id 从1~10所有数据:

    cust_id:[1 TO 10]

  • sort: 排序, 例如, 根据cust_id倒序排序:

    cust_id desc

  • start, rows: 分页展示, start:从第几条数据开始, rows:几条数据, 例如
  • fl: 要展示哪些字段, 字段间用逗号分隔, 例如:

    cust_id, cust_name

  • df: 默认搜索域, 根据这个field进行搜索匹配, 指定一个schema.xml中的field的name值: 如:

    cust_name

  • wt: 指定输出格式,可以有 xml, json, php, phps
  • hl: 是否高亮 ,设置高亮Field,设置格式前缀和后缀。


当然, 我们在项目开发的过程中, 不可能通过这种图形界面来操作, 我们一般会通过solr为我们提供的API来操作solr进行分词操作.

java代码的实现:

  • 添加和删除
package cn.itcast.solr;

import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;

public class IndexManagerTest {

    // 添加
    @Test
    public void testIndexCreate() throws Exception{
        //创建和Solr服务端连接
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
        
        //创建solr文档对象
        SolrInputDocument doc = new SolrInputDocument();
        //域要先定义后使用,还有注意必须要有id主键域
        //solr中没有专用的修改方法, 会自动根据id进行查找,如果找到了则删除原来的将新的加入就是修改,如果没找到,将新的直接加入则就是新增
        doc.addField("cust_id", 1);
        doc.addField("cust_name", "张三");
        doc.addField("cust_source", "湖南");
        doc.addField("cust_industry", "前端开发工程狮");
        
        //将文档加入solrServer对象中
        solrServer.add(doc);

        //提交
        solrServer.commit();
    }
    
    // 删除
    @Test
    public void testIndexDel() throws Exception{
        //创建和Solr服务端连接
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
        
        //根据主键id进行删除
        //solrServer.deleteById("a001");
        
        //根据查询删除,这里是删除所有*:*
        solrServer.deleteByQuery("*:*");
        //提交
        solrServer.commit();
    }
}
  • 查询操作
package cn.itcast.solr;

import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.junit.Test;

public class IndexSearchTest {

    @Test
    public void testIndexSearch1() throws Exception{
        //连接solr服务端
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
        
        //创建solr查询条件对象
        SolrQuery solrQuery = new SolrQuery();
        //查询所有
        solrQuery.setQuery("*:*");
        
        //查询并获取查询响应对象
        QueryResponse queryResponse = solrServer.query(solrQuery);
        //从查询响应中获取查询结果集对象
        SolrDocumentList results = queryResponse.getResults();
        //打印一共查询到多少条记录,也就是记录总数
        System.out.println("=====count====" + results.getNumFound());
        //遍历查询结果集
        for(SolrDocument doc : results){
            System.out.println("============="+doc.get("cust_id"));
            System.out.println("============="+doc.get("cust_name"));
            System.out.println("============="+doc.get("cust_source"));
            System.out.println("============="+doc.get("cust_industry"));
            System.out.println("====================================================");
        }
    }
    
    @Test
    public void testIndexSearch2() throws Exception{
        //连接solr服务端
        SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
        
        //创建solr查询条件对象
        SolrQuery solrQuery = new SolrQuery();
        //查询关键字输入
        solrQuery.setQuery("张三");
        //设置默认搜索域
        solrQuery.set("df", "cust_name");
        //设置过滤查询
        solrQuery.addFilterQuery("cust_id:[1 TO 100]");
        //设置排序,这里是降序
        solrQuery.setSort("cust_id", ORDER.desc);
        //=======设置分页========
        //设置起始条数
        solrQuery.setStart(0);
        //设置查询多少条
        solrQuery.setRows(50);
        
        //========设置高亮显示=======
        //高亮默认是关闭的,所以要手动开启
        solrQuery.setHighlight(true);
        //设置需要高亮显示的域
        solrQuery.addHighlightField("cust_name");
        //设置高亮前缀
        solrQuery.setHighlightSimplePre("<span style=\"color:red\">");
        //设置高亮后缀
        solrQuery.setHighlightSimplePost("</span>");
        
        //===================查询并获取查询响应对象=====================================
        QueryResponse queryResponse = solrServer.query(solrQuery);
        //从查询响应中获取查询结果集对象
        SolrDocumentList results = queryResponse.getResults();
        //打印一共查询到多少条记录,也就是记录总数
        System.out.println("=====count====" + results.getNumFound());
        //遍历查询结果集
        for(SolrDocument doc : results){
            System.out.println("============="+doc.get("cust_id"));
            //获取高亮
            Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
            List<String> list = highlighting.get(doc.get("cust_id")).get("cust_name");
            if(list != null && list.size() > 0){
                String hlName = list.get(0);
                System.out.println("=======high lighting=====" + hlName);
            }
            
            System.out.println("============="+doc.get("cust_name"));
            System.out.println("============="+doc.get("cust_source"));
            System.out.println("============="+doc.get("cust_industry"));
            System.out.println("====================================================");
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/dagger9527/p/11836736.html