solr 全文检索引擎安装及使用(docker版)

1,519 阅读5分钟

solr是什么

Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。

为什么要用solr

现实生活中我们都知道大多数网站或应用都必须具有某种搜索功能,问题是搜索功能往往是巨大的资源消耗并且它们由于沉重的数据库加载而拖垮你的应用的性能,而数据库本身不能实现分词效果,而只能使用模糊查询,但是模糊查询非常低效,查询速度比较慢,由于在实际生活中,一般搜索是用的比较多的,这样数据库压力自然就很大,所以我们就让供专业的solr来做搜索功能。

solr 怎么用

安装过程

目前使用的是 8.1.1 版本

目录结构

dockerfile

FROM solr
user root


# 安装中文分词
WORKDIR /opt/solr/server/solr-webapp/webapp/WEB-INF/lib
ADD ik-analyzer-solr5-5.x.jar .
ADD solr-analyzer-ik-5.1.0.jar .
WORKDIR /opt/solr/server/solr-webapp/webapp/WEB-INF
ADD ext.dic .
ADD stopword.dic .
ADD IKAnalyzer.cfg.xml .

user solr
WORKDIR /opt/solr

# 由于使用数据卷导致目录权限提升为root所以重新分配目录权限
ENTRYPOINT ["docker-entrypoint.sh"]
                        #容器启动时调整目录权限
CMD solr-foreground && chown -R solr /var/solr/data


docker-compose.yml

version: '3.1'
services:
  solr:
    build: ikanalyzer
    restart: always
    container_name: solr
    ports:
      - 8983:8983
    volumes:
      - ./solrdata:/var/solr/data

创建solr域

直接创建域会提示找不到配置文件,所以需要先拷贝配置文件

直接点击创建后/var/solr/data会创建对应域名称的文件夹,之后将/opt/solr-8.1.1/server/solr/configsets/_default/conf下的配置文件拷贝至新创建的文件夹下,再次创建域创建成功。

命令:cp -r /opt/solr-8.1.1/server/solr/configsets/_default/conf /var/solr/data/new_core

添加中文分词类型配置

由于数据卷映射了/var/solr/data 目录,所以找到managed-schema文件,文件最后添加如下配置后reload域

 <!-- IK分词 -->
     <fieldType name="text_ik" class="solr.TextField">
        <analyzer type="index">
            <tokenizer class="org.apache.lucene.analysis.ik.IKTokenizerFactory" useSmart="true"/>
        </analyzer>
        <analyzer type="query">
            <tokenizer class="org.apache.lucene.analysis.ik.IKTokenizerFactory" useSmart="true"/>
        </analyzer>
     </fieldType>

测试中文分词

添加需要检索的域字段

找到managed-schema文件最后添加如下配置后reload域

 <field name="solr_id" type="text_ik" indexed="true" stored="true"/>
 <field name="solr_title"  type="text_ik" indexed="true" stored="true"/>
 <field name="solr_content"  type="text_ik" indexed="true" stored="true"/>
 <field name="solr_keyword" type="text_ik" indexed="true" stored="true" />
  • name:字段名称

  • type:字段类型

  • indexed:是否索引

  • stored:是否存储

添加检索数据

数据如下:

{
          "solr_id": "1",
          "solr_title": "我这个是手机哦",
          "solr_content": "\n智能手机,是指像个人电脑一样,具有独立的操作系统,独立的运行空间,可以由用户自行安装软件、游戏、导航等第三方服务商提供的程序,并可以通过移动通讯网络来实现无线网络接入手机类型的总称。 智能手机具有优秀的操作系统、可自由安装各类软件(仅安卓系统)、完全大屏的全触屏式操作感这三大特性,其中 苹果、华为(HUAWEI)、三星、诺基亚、HTC(宏达电) 这五大品牌在全世界最广为皆知,而小米(Mi)、\n",
          "solr_keyword": "手机"
}

查询

根据单个域字段检索数据

  • q:查询条件,: 为查询所有域,单独查询某个域如:tb_item_title:手机

  • fq: 过滤条件

  • sort:排序条件

  • start,rows:分页条件

  • fl:字段列表返回域,如只希望返回 id

  • df:默认搜索域,如之前配置的复制域 tb_item_keywords

根据复制域查询多个域字段的值(关键)

managed-schema文件添加如下配置后reload域
# 复制域将多个字段域复制到一个域里
<field name="solr_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="solr_id" dest="solr_keywords"/>
<copyField source="solr_title" dest="solr_keywords"/>
<copyField source="solr_content" dest="solr_keywords"/>
<copyField source="solr_keyword" dest="solr_keywords"/>
测试查询

删除

根据 ID 删除

<delete>
    <id>536563</id>
</delete>
<commit />

根据域字段条件删除

<delete>
    <query>*:*</query>
</delete>
<commit/>

如:

<delete>
    <query>solr_content:手机</query>
</delete>
<commit/>

spring boot 集成 solr

solr关键pom

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-solr</artifactId>
 </dependency>

solr关键yml

spring:
  application:
  # solr 配置
  data:
    solr:
      host: http://ip:port/solr/new_core

使用

package com.fjhckj.springcloudsolr.solr.controller;

import com.fjhckj.springcloudsolr.solr.entity.Solr;
import com.fjhckj.springcloudsolr.solr.service.SolrService;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("solr")
public class SolrController {
    @Autowired
    private SolrService solrService;

    @Autowired
    private SolrClient client;


    /**
     * 从数据库查询数据后插入solr
     */
    @RequestMapping(value = "add")
    public void add(){
        List<Solr> solrList = solrService.findList(new Solr());
        for(Solr solr: solrList){
            SolrInputDocument document = new SolrInputDocument();
            document.setField("id", UUID.randomUUID().toString());
            document.setField("solr_id",solr.getId());
            document.setField("solr_title",solr.getTitle());
            document.setField("solr_content",solr.getContent());
            document.setField("solr_keyword",solr.getKeyword());
            try {
                client.add(document);
                client.commit();
            } catch (SolrServerException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

    /**
     * 删除
     * @param condition
     */
    @RequestMapping(value = "delete/{condition}")
    public void testDeleteDocument(@PathVariable String condition) {
        try {
            client.deleteByQuery(condition);
            client.commit();
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 查询索引库
     */
    @ResponseBody
    @RequestMapping(value = "queryDocument/{key}")
    public SolrDocumentList queryDocument(@PathVariable String key) {
        // 创建查询对象
        SolrQuery query = new SolrQuery();

        // 设置查询条件
        query.setQuery(key);

        // 设置分页
        query.setStart(0);
        query.setRows(10);

        // 设置默认搜索域
        query.set("df", "solr_keywords");

        // 设置高亮显示
//        query.setHighlight(true);
//        query.addHighlightField("solr_content");
//        query.setHighlightSimplePre("<span style='color:red;'>");
//        query.setHighlightSimplePost("</span>");

        try {
            // 执行查询操作
            QueryResponse response = client.query(query);

            // 获取查询结果集
            SolrDocumentList results = response.getResults();

            // 获取高亮显示
//            Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();

            // 遍历结果集
            return results;
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
       return null;
    }

}


遇到的问题

solr用户权限不足

错误信息: cp: cannot create regular file '/var/solr/data/solr.xml': Permission denied 错误原因:使用数据卷导致/var/solr/data 目录权限只归属root

解决方案

在dockerfile 中增加如下代码


ENTRYPOINT ["docker-entrypoint.sh"]
                        #容器启动时调整目录权限
CMD solr-foreground && chown -R solr /var/solr/data