• 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("====================================================");
        	}
        }
    }
    
  • 相关阅读:
    闭包
    保存数据
    Browers Object Model
    JavaScript中的null和undefined
    魔法查询函数
    《黑客与画家》 读书感想
    CakePHP查询数据
    HDFS写入和读取流程
    回调函数
    JAVA中的指针
  • 原文地址:https://www.cnblogs.com/dagger9527/p/11836736.html
Copyright © 2020-2023  润新知