SpringBoot 集成 Solr 实现高效全文检索服务

科长
2024-11-18 / 0 评论 / 5 阅读 / 正在检测是否收录...

简介

Solr 是一个基于 Apache Lucene 构建的开源搜索平台。它提供了强大的搜索功能、高效的索引机制和丰富的配置选项,使得开发者能够轻松构建高性能的搜索应用。

Solr 具有易于使用的 Web 管理界面,方便进行配置和监控。它支持多种数据格式的索引和搜索,能够处理大量的数据,并提供了诸如分页、排序、过滤、高亮显示搜索结果等功能。

架构

有了 MySQL 还有必要用 Solr 吗

即使已经使用了 MySQL 这样的关系型数据库,在某些情况下使用 Solr 仍然是有必要的。

MySQL 擅长处理结构化数据的存储和事务操作,但在搜索功能方面存在一些局限性。例如,对于复杂的全文搜索、模糊搜索、相关性排序等需求,MySQL 可能无法提供高效和灵活的解决方案。

而 Solr 专门为搜索进行了优化,能够快速处理大规模的文本数据搜索,并提供更精确的搜索结果排序和相关性计算。

举例来说,如果您的应用需要快速搜索大量的文章内容、产品描述等文本信息,并且对搜索的响应速度和准确性要求较高,那么单独依靠 MySQL 可能无法满足需求,此时结合 Solr 可以显著提升搜索体验。

另外,如果需要实现实时搜索、动态索引更新等功能,Solr 也更具优势。

安装Solr

下载运行

前往solr的官方下载地址:

https://solr.apache.org/downloads.html

Solr 9.x 版本最低运行要求是 Java 11,我一直使用的是 Java 8 所以这里我将使用 Solr 8.x 作为本次的教程版本。

选择版本

下载后将其解压会得到如下的目录结构:

solr目录

打开终端,进入bin目录中启动Solr服务:

启动

Windows用户则只需要执行下面的命令:

solr start

Solr 面板

安装中文分词器

中文具有独特的语言结构和语义表达,不像英文等语言,单词之间通常有明显的空格分隔。如果直接使用 Solr 默认的分词器处理中文文本,可能会将中文拆分成单个的汉字,而不是按照中文的词语进行切分。

前往Maven仓库下载分词依赖:

https://mvnrepository.com/artifact/com.github.magese/ik-analyzer/8.5.0

下载Jar

将下载下来的 ik-analyzer-8.5.0.jar 放入到 solr-8.11.3/server/solr-webapp/webapp/WEB-INF/lib

放入依赖

我们在终端使用命令创建一个 core 来测试一下分词器:

 ./solr create -c ik_core 

创建core

然后在 solr-8.11.3/server/solr 下可以看到一个名为 ik_core 的目录:

ik_core目录

conf 目录下编辑 managed-schema 文件并写入以下内容:

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

添加分词器

重启Solr服务:

重启服务

测试分词器

Solr Admin 中,也就是solr的web界面,选择我们创建的 ik_coreAnalysis 中测试分词效果(Analyse Fieldname / FieldType 选择为 text_ik):

分词效果

集成到SpringBoot

创建SpringBoot项目

SpringBoot项目的创建可以借助IDE完成,这里就不再叙述了。

创建项目

添加maven依赖

在项目的 pom.xml 中添加新的依赖:

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

创建配置

application.yml中添加solr的配置信息:

solr:
  host: http://127.0.0.1:8983/solr

创建配置类:

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SolrConfig {

    @Value("${solr.host}")
    private String solrHost;

    @Bean
    public SolrClient solrClient() {
        return new HttpSolrClient.Builder(solrHost).build();
    }
}

创建文档索引

在查询数据之前,我们需要在solr中导入我们的数据,并建立索引。

第一种方式来添加文档比较简单:

@Resource
private SolrClient solrClient;

public void indexQuestion() throws Exception{
    // 创建一个文档对象
    SolrInputDocument inputDocument = new SolrInputDocument();
  // 添加字段
    inputDocument.addField("id", "1");
    inputDocument.addField("name", "名称1");
    inputDocument.addField("content", "内容1");
  inputDocument.addField("category", "类别1");
    // 将文档写入索引库中
    solrServer.add("ik_core", inputDocument);
    // 提交
    solrServer.commit("ik_core");
}

第二种方式则是实用Java Bean的方式,其字段属性使用Solr提供的的 @Field 注解标柱:

@Data
public class Document {
    @Field
    private String id;
    @Field
    private String name;
    @Field
    private String content;
      @Field
      private String category;
}

然后实例化Bean,并将其添加到我们创建的 ik_core 中进行索引:

@Resource
private SolrClient solrClient;

public boolean indexQuestion() throws SolrServerException, IOException {

    // 实例化并添加 Document 对象
    Document doc1 = new Document();
    doc1.setId("1");
    doc1.setName("国内新能源汽车销量持续攀升");
    doc1.setContent("今年以来,国内新能源汽车市场表现强劲,销量不断增长。各大厂商纷纷推出新款车型,技术创新不断。");
    doc1.setCategory("汽车");
    solrClient.addBean("ik_core", doc1);

    Document doc2 = new Document();
    doc2.setId("2");
    doc2.setName("国内电商行业发展新趋势");
    doc2.setContent("随着数字化转型的加速,国内电商行业呈现出直播带货、社交电商等新趋势,消费者购物方式发生显著变化。");
    doc2.setCategory("电商");
    solrClient.addBean("ik_core", doc2);

    Document doc3 = new Document();
    doc3.setId("3");
    doc3.setName("国内5G网络建设加速推进");
    doc3.setContent("国内5G网络覆盖范围持续扩大,为智能制造、智慧城市等领域的发展提供了有力支撑。");
    doc3.setCategory("通信");
    solrClient.addBean("ik_core", doc3);

    Document doc4 = new Document();
    doc4.setId("4");
    doc4.setName("国内旅游市场逐渐复苏");
    doc4.setContent("在疫情防控形势好转的背景下,国内旅游市场迎来复苏,各地旅游景点游客数量逐步增加。");
    doc4.setCategory("旅游");
    solrClient.addBean("ik_core", doc4);

    Document doc5 = new Document();
    doc5.setId("5");
    doc5.setName("国内医疗改革取得新进展");
    doc5.setContent("近年来,国内医疗改革不断深化,医保政策优化,医疗服务质量得到提升。");
    doc5.setCategory("医疗");
    solrClient.addBean("ik_core", doc5);

    // 提交
    UpdateResponse updateResponse = solrClient.commit("ik_core");
    return updateResponse != null && updateResponse.getStatus() == 0;
}

当有了这些数据后,我们即可对这些数据进行检索操作,第一次我们写简单点进行查询:

public void query() throws SolrServerException, IOException {
    // 创建查询语句
    SolrQuery query = new SolrQuery();
    // 设置查询条件
    query.set("q", "id:1");
    // 执行查询
    QueryResponse queryResponse = solrClient.query("ik_core", query);
    // 取文档列表
    SolrDocumentList documentList = queryResponse.getResults();
    for (SolrDocument solrDocument : documentList) {
        System.out.println("id:"+solrDocument.get("id")+" ");
        System.out.println("名称:"+solrDocument.get("name")+" ");
        System.out.println("内容:"+solrDocument.get("content")+" ");
        System.out.println("类别:"+solrDocument.get("category")+" ");
    }
      // 也可以反序列化为Java Bean
    List<Document> documents = queryResponse.getBeans(Document.class);
    for (Document document : documents) {
        System.out.println("id:" + document.getId());
        System.out.println("名称:" + document.getName());
        System.out.println("内容:" + document.getContent());
        System.out.println("类别:" + document.getCategory());
    }
}

接下来可以构造条件丰富的查询:

 public void query() throws Exception {
    // 创建查询语句
    SolrQuery query = new SolrQuery();
    // 设置查询关键字
    query.set("q", "国内");
    // 按照id降序排列
    query.setSort("id", SolrQuery.ORDER.desc);
    // 分页条件
    query.setStart(0);
    query.setRows(2);
    // 在指定的字段中进行查询
    query.set("df", "name");
    // 设置高亮
    query.setHighlight(true);
    // 设置高亮的字段
    query.addHighlightField("name,content");
    // 设置高亮的样式
    query.setHighlightSimplePre("<font color='red'>");
    query.setHighlightSimplePost("</font>");
    // 执行查询
    QueryResponse queryResponse = solrClient.query("ik_core", query);
    // 返回高亮显示结果
    Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
    System.out.println(highlighting);
    // 获取文档列表
    SolrDocumentList documentList = queryResponse.getResults();
    System.out.println("总记录数:" + documentList.getNumFound());
    for (SolrDocument solrDocument : documentList) {
        System.out.println("id:" + solrDocument.get("id") + " ");
        System.out.println("名称:" + solrDocument.get("name") + " ");
        System.out.println("内容:" + solrDocument.get("content") + " ");
        System.out.println("类别:" + solrDocument.get("category") + " ");
    }
}

删除文档则可以使用id字段进行删除:

public void deleteQuestion() throws SolrServerException, IOException {
   solrClient.deleteById("ik_core", "1");
   // 提交
   solrClient.commit("ik_core");
}

总体的来说 Solr 是一款开源的高性能搜索平台,具有强大搜索功能、可扩展性、丰富特性、灵活配置且易于集成,能满足各种复杂搜索和数据管理需求。

0

评论 (0)

取消