初识Solr搜索引擎

MOKE 2019-02-28 PM 32℃ 0条

需求:首页的搜索功能,需要根据搜索条件进行分词,查询出需要的结果,然后将分词高亮显示


下载并测试Solr

下载配置

1.官网下载:地址
2.将压缩包解压到自定义目录,命令提示符窗口进入到 solr-7.3.1bin 目录下,通过 solr start 命令,启动 Solr 服务;访问端口为8983,可以通过 127.0.0.1:8983 访问 Solr 网页
1
注:重启命令 :solr restart -p 8983
3.创建索引库:solr create -c firstcore,firstcore是索引库的名字;刷新网页,能看到我们创建的索引库
2

Java测试

Java 就是通过 Solrj 来操作 Solr 的。它提供了一些增、删、改、查的方法。
1.在 pom.xml 中引入依赖 solr-solrj

        <dependency>
          <groupId>org.apache.solr</groupId>
          <artifactId>solr-solrj</artifactId>
          <version>7.3.0</version>
        </dependency>

2.spring配置文件applicationContext-solr.xml管理

        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="httpSolrClient" class="org.apache.solr.client.solrj.impl.HttpSolrClient">
            <!-- 将我们建的索引库注入到HttpSolrClient对象的Builder属性中 -->
            <constructor-arg name="builder" value="http://localhost:8983/solr/firstcore"/>
        </bean>
    
        </beans>

3.创建测试类:TestSolrJ.java
使用对象:SolrClient(HttpSolrClient)、SolrInputDocument

        @ContextConfiguration(locations = {"classpath:applicationContext-solr.xml"})//加载spring配置文件
        public class TestSolrJ extends AbstractJUnit4SpringContextTests {//继承测试基类
            @Autowired
            private SolrClient solrServer;//通过spring注入SolrClient对象
        
            @Test
            public void testSave() throws Exception {   
                //1.创建一个文档对象
                SolrInputDocument inputDocument = new SolrInputDocument();
                inputDocument.addField( "id", "10" );
                inputDocument.addField( "item_title", "hello solr" );
                inputDocument.addField( "item_image", "...." );
                inputDocument.addField( "author", "moke" );
                //2.将文档写入索引库中
                solrServer.add( inputDocument );
                //3.提交
                solrServer.commit();
            }
        }

4.运作测试类,访问 Solr 网页,执行Execute Query,能够看到我们添加到索引库的数据
3
4
5.由上图可知查询出来的结果除了 id 都是 ArrayList 集合形式 [],如果取值的话转换起来会很麻烦,所以需要对solr-7.7.0serversolrfirstcoreconf目录下的managed-schema配置文件进行修改:
5
属性解释:
name:字段的名字
type:字段的数据类型
multiValued:是否有多值,有多值时设置为 true,否则设置为 false
indexed:是否创建索引
required:是否必须
stored:是否存储数据,如果设置为 false 则不存储,结合 docValues="false" 使得查询不返回结果
修改:将type类型由text_general改为String
6
重启solr,再次查询:
7


Solr在项目中的应用

分词器

Solr 可通过自带的分词器 smartcn 或者第三方分词器 IKAnalyzer 来实现,smartcn逐个字分词,而IK是按照词语分词
添加IK分词器步骤:

  1. 下载 IKAnalyzer 分词器 Jar 包
  2. 压缩包解压后,将其中的两个 Jar 包放入 solr-7.7.0serversolr-webappwebappWEB-INFlib 下
  3. 配置 solr-7.7.0serversolrmycoreconf 下的 managed-schema 文件,添加分词器和需要分词的字段
        <!-- 添加ik分词器 -->
        <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>

managed-schema

  1. 对需要分词的字段修改其 type,例如标题需要分词:
        <field name="title" type="text_ik" indexed="true" stored="true" required="true" multiValued="false" />
  1. 配置其它字段名和类型,否则会查询出集合类型的数据:
        <field name="comment_num" type="string"/>
        <field name="category" type="string"/>
        ...

整合SSM

  1. 在 web.xml 中引入 applicationContext-solr.xml 配置文件
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                ...
                 classpath:applicationContext-solr.xml
            </param-value>
        </context-param>
  1. 在Service层的实现类SolrServiceImpl中添加查询方法:
    使用对象:HttpSolrClient、SolrQuery、QueryResponse
        @Autowired
        HttpSolrClient solrClient;//注入HttpSolrClient
        @Override
         public Page<UserContent> findByKeyWords(String keyword, Integer pageNum, Integer pageSize) {
            SolrQuery solrQuery = new SolrQuery( );//创建Solr查询条件对象
            //设置查询条件
            solrQuery.setQuery( "title:"+keyword );//keyword为jsp页面传递过来的查询条件
            //设置高亮
            solrQuery.setHighlight(true);
            solrQuery.addHighlightField( "title" );
            solrQuery.setHighlightSimplePre( "<span style='color:red'>" );
            solrQuery.setHighlightSimplePost( "</span>" );
    
            //分页
            if (pageNum == null || pageNum < 1) {
                pageNum = 1;
            }
            if (pageSize == null || pageSize < 1) {
                pageSize = 7;
            }
            solrQuery.setStart( (pageNum-1)*pageSize );
            solrQuery.setRows( pageSize );
            
            //开始查询
            try {
                QueryResponse response = solrClient.query(solrQuery);//通过条件查询索引库
                //通过查询结果获得高亮数据集合
                Map<String,Map<String, List<String>>> highlighting = response.getHighlighting();
                //通过查询结果获得结果集
                SolrDocumentList resultList = response.getResults();
                //通过结果集获得总数量
                long totalNum = resultList.getNumFound();
                List<UserContent> list = new ArrayList<UserContent>();
                for(SolrDocument solrDocument:resultList){
                    //创建文章对象
                    UserContent content = new UserContent();
                    //通过结果集获取查询到的所有信息
                    String id = (String) solrDocument.get("id");
                    Object commentNum = solrDocument.get("comment_num");
                    Object category = solrDocument.get( "category" );
                    //取得高亮数据集合中的文章标题
                    Map<String, List<String>> map = highlighting.get(id);
                    //通过id获取相应文章的高亮部分的集合
                    String title = map.get("title").get(0);
                    //获取高亮部分的第一个即标题(还有文章内容等包含keyword的高亮部分)
                    //将获取到的信息都封装到对象中,并把对象添加进List集合
                    content.setId( Long.parseLong(id) );
                    content.setCommentNum( Integer.parseInt( commentNum.toString() ) );
                    content.setCategory( category.toString() );
                    content.setTitle( title );//将获得的高亮标题封装进对象,即带有span标签
                    list.add(content);
                }
                //将查询到的数据通过分页插件分页,返回分页对象page
                PageHelper.startPage(pageNum, pageSize);//开始分页
                PageHelper.Page page = PageHelper.endPage();//分页结束
                page.setResult(list);
                page.setTotal(totalNum);
                return page;
            } catch (SolrServerException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

注:
1.调用此查询方法前,需要通过SolrInputDocument和HttpSolrClient 将数据先添加进索引库(详见Java测试)
2.其它对相关对象的增删改操作的同时,需要对索引库也进行增删改,即controller中除了调用相关Service的增删改方法,还需要调用SolrService的增删改方法

Tomcat运行Solr

默认 Solr 是在 Jetty 服务器下运行的,改为tomcat上运行步骤:

  1. 将 solr-7.7.0serversolr-webapp 下的 webapp 文件复制到 Tomcat 的 webapps 目录下,并重命名为 Solr
  2. 将 solr-7.7.0serverlibext 目录下的所有 Jar 包复制到刚才重命名的 solrWEB-INFlib 下
  3. 将 solr-7.7.0serverlib 下以 metrics 开头的5个 Jar 包也复制到刚才重命名的 solrWEB-INFlib 下
  4. 在刚才重命名的 solrWEB-INF 下新建 classes 文件夹,并将 solr-7.7.0serverresources 下的 log4j.properties 文件复制到刚刚新建的 classes 文件夹下
  5. 将 solr-7.7.0server 目录下的 Solr 文件夹复制到自定义路径下,然后重命名为 solr_home
  6. 修改之前重命名的 solrWEB-INF 下的 web.xml 文件:
    (1)添加env-entry

(2)将 security-constraint 标签内的内容注释掉

        <env-entry>
           <env-entry-name>solr/home</env-entry-name>
           <env-entry-value>D:/solr_home</env-entry-value><!-- 你自己的目录 -->
           <env-entry-type>java.lang.String</env-entry-type>
        </env-entry>
  1. 启动tomcat,通过:localhost:8080/solr 即可访问Solr
标签: Solr

非特殊说明,本博所有文章均为博主原创。

评论啦~