springboot整合es进行搜索

这篇具有很好参考价值的文章主要介绍了springboot整合es进行搜索。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.Elasticsearch 安装

1.1 下载软件

  • Elasticsearch 的官方地址:https://www.elastic.co/cn/
  • 这里选择下载 7.8.0 版本
  • 下载地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

Elasticsearch 分为 Linux 和 Windows 版本,这里我们只是做测试,因此下载 windows 版本即可。

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

1.2 安装软件

Windows 版的 Elasticsearch 的安装很简单,解压即安装完毕,解压后的 Elasticsearch 的目录结构如下:

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

目录 含义
bin 可执行脚本目录
config 配置目录
jdk 内置JDK目录
lib 类库
logs 日志目录
modules 模块目录
plugins 插件目录

1.3 安装 ik 中文分词器

🏠 下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.8.0

  • ik_max_word:会将文本做最细粒度的拆分
  • ik_smart:会将文本做最粗粒度的拆分

将解压后的后的文件夹放入 ES 根目录下的 plugins 目录下。

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

1.4 启动ES

解压后,进入 bin 文件目录,点击 elasticsearch.bat 文件启动 ES 服务:

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

⚠️ 注意:

  • 9300 端口为 Elasticsearch 集群间组件的通信端口。
  • 9200 端口为浏览器访问的 http 协议 RESTful 端口。

💻 浏览器访问地址:http://localhost:9200

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

1.5 问题解决

  • Elasticsearch 是使用 java 开发的,且 7.8 版本的 ES 需要 JDK 版本 1.8 以上,默认安装包带有 jdk 环境,如果系统配置 JAVA_HOME,那么使用系统默认的 JDK,如果没有配置使用自带的 JDK,一般建议使用系统配置的 JDK。

  • 双击启动窗口闪退,通过路径访问追踪错误,如果是“空间不足”,请修改 config/jvm.options 配置文件

    # 设置 JVM 初始内存为 1G。此值可以设置与-Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存
    # Xms represents the initial size of total heap space
    # 设置 JVM 最大可用内存为 1G
    # Xmx represents the maximum size of total heap space
    
    -Xms1g
    -Xmx1g
    

2.Kibana 安装 & 使用

Elasticsearch 的开源分析可视化工具,与存储在 Elasticsearch 中的数据进行交互。

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

2.1 下载软件

Elasticsearch 下载的版本是 7.8.0,这里我们选择同样的 7.8.0 版本

下载地址:https://www.elastic.co/cn/downloads/past-releases#kibana

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

2.2 安装软件

解压即安装完毕,解压后的 Kibana 的目录结构如下:

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

修改配置文件:kibana.yml

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

添加如下信息:

# 服务端口
server.port: 5601
# 国际化 - 中文
i18n.locale: "zh-CN"
# ES 服务主机地址
elasticsearch.hosts: ["http://localhost:9200"]

server.ssl.enabled: false

2.3 启动 Kibana

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

访问浏览器:http://localhost:5601/

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

3.实战开发-前提准备

3.1 开发背景

假设有一个博客模块,即有一个博客圈,用户可以通过搜索来获取与自己输入的关键字相关的数据列表,类似于CSDN的搜索。

由于只是 demo,因此这里会设计的很简单。

  • 不支持通过作者进行搜索。

3.2 数据库表设计

# 如果存在 es_demo 数据库则删除
DROP DATABASE IF EXISTS `es_demo`;
# 创建新数据库
CREATE DATABASE `es_demo`;

# 创建一张博客表
CREATE TABLE `blog`(
	`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键id',
	`user_id` BIGINT NOT NULL COMMENT '用户id(雪花算法生成)',
	`title` VARCHAR(255) NOT NULL COMMENT '标题',
	`tags` VARCHAR(64) NOT NULL COMMENT '标签',
	`introduce` VARCHAR(512) NOT NULL COMMENT '介绍',
	`content` TEXT NOT NULL COMMENT '文章内容', 
	`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
	`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
	PRIMARY KEY(`id`),
	KEY `idx_user_create`(`user_id`,`create_time` DESC)
)ENGINE=INNODB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='博客信息表';

3.3 创建es索引与映射

PUT /blog
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "userId": {
        "type": "long"
      },
      "title": {
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "type": "text"
      },
      "tags": {
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "type": "text"
      },
      "introduce":{
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "type": "text"
      },
      "content":{
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart",
        "type": "text"
      },
      "createTime":{
        "format": "yyyy-MM-dd HH:mm:ss",
        "type": "date"
      },
      "updateTime":{
        "format": "yyyy-MM-dd HH:mm:ss",
        "type": "date"
      }
    }
  }
}

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

3.4 es文档数据

其实按照正常的逻辑,应当在往数据库表添加记录后也写入到es中,可以使用java代码实现。但这里为了简单起见,我们直接往es中添加数据进行测试。

POST /blog/_doc/1000
{
  "id":1000,
  "userId":1626989073847750657,
  "title":"Java语言",
  "introduce":"Java的起源",
  "content":"Java最初是由任职于太阳微系统的詹姆斯-高斯林(James-Gosling)等人于1990年代初开发。最初被命名为Oak;当时发现Oak被其他公司注册了,不得不重新起名,当时他们正在咖啡馆喝着印尼爪哇(JAVA)岛出产的咖啡,有人提议就叫JAVA怎么样,然后就这样定下来了。",
  "tags":"编程,java,语言",
  "createTime":"2023-03-23 00:40:20",
  "updateTIme":"2023-03-23 00:40:20"
}

POST /blog/_doc/1001
{
  "id":1001,
  "userId":1626989073847750657,
  "title":"C语言",
  "introduce":"C的起源",
  "content":"C语言是由美国贝尔实验室的Dennis Ritchie于1972年设计发明的,最初在UNIX操作系统的DEC PDP-11计算机上使用。它由早期的编程语言BCPL(Basic Combind Programming Language)发展演变而来。",
  "tags":"编程,C,语言",
  "createTime":"2023-03-23 00:40:20",
  "updateTIme":"2023-03-23 00:40:20"
}

POST /blog/_doc/1002
{
  "id":1002,
  "userId":1626989073847750657,
  "title":"C与JAVA语言",
  "introduce":"c和java关系",
  "content":"C语言和Java都是计算机编程语言,但它们有很多不同之处。C语言是一种面向过程的编程语言,而Java是一种面向对象的编程语言。",
  "tags":"C,java,语言",
  "createTime":"2023-03-23 00:40:20",
  "updateTIme":"2023-03-23 00:40:20"
}

4.实战开发-后端代码

4.1 pom.xml依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.fox</groupId>
    <artifactId>elasticsearch-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.8.0</version>
        </dependency>
        <!--fastjson依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.33</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.7</version>
        </dependency>
    </dependencies>


</project>

4.2 application.yml配置

server:
  # 服务端口
  port: 9999
elasticsearch:
  # es访问ip
  hostname: 127.0.0.1
  # es访问port
  port: 9200
  blog:
    # 访问索引
    index: blog
    # 搜索返回字段
    source_fields: id,userId,title,introduce,createTime

4.3 entity包

4.3.1 Result.java

package com.fox.es.entity;

import lombok.Data;

/**
 * 统一返回对象
 * 
 * @author 狐狸半面添
 * @create 2023-03-22 18:34
 */
@Data
public class Result {
    private Integer code;
    private String msg;
    private Object data;

    private Result(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    private Result(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public static Result ok() {
        return new Result(200, "success");
    }

    public static Result ok(Object data) {
        return new Result(200, "success", data);
    }

    public static Result error(String msg) {
        return new Result(500, msg);
    }

    public Result error(Integer code, String msg) {
        return new Result(code, msg);
    }

}

4.3.2 JacksonObjectMapper.java

package com.fox.es.entity;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;

/**
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
 *
 * @author 狐狸半面添
 * @create 2023-01-18 20:34
 */
public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(FAIL_ON_UNKNOWN_PROPERTIES);


        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))

                .addSerializer(BigInteger.class, ToStringSerializer.instance)
                .addSerializer(Long.class, ToStringSerializer.instance)
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

4.4 config包

4.4.1 ElasticsearchConfig.java

package com.fox.es.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 狐狸半面添
 * @create 2023-03-22 17:51
 */
@Configuration
public class ElasticsearchConfig {
    @Value("${elasticsearch.hostname}")
    private String hostname;
    @Value("${elasticsearch.port}")
    private Integer port;

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        RestClientBuilder builder = RestClient.builder(
                new HttpHost(hostname, port, "http")
        );
        return new RestHighLevelClient(builder);
    }
}

4.4.2 WebMvcConfig.java

package com.fox.es.config;

import com.fox.es.entity.JacksonObjectMapper;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;

/**
 * @author 狐狸半面添
 * @create 2023-02-11 23:25
 */

@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {

    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        converters.add(0, messageConverter);
    }
}

4.5 BlogSimpleInfoDTO.java

package com.fox.es.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * @author 狐狸半面添
 * @create 2023-03-22 21:33
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BlogSimpleInfoDTO {
    /**
     * 主键id
     */
    private Integer id;
    /**
     * 用户id
     */
    private Long userId;
    /**
     * 标题
     */
    private String title;
    /**
     * 介绍
     */
    private String introduce;
    /**
     * 创建时间
     */
    private LocalDateTime createTime;

}

4.5 主启动类

package com.fox.es;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author 狐狸半面添
 * @create 2023-03-22 18:07
 */
@SpringBootApplication
public class ElasticsearchDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(ElasticsearchDemoApplication.class, args);
    }
}

4.6 ⭐测试是否连接 es 成功

package com.fox.es.controller;

import com.fox.es.entity.Result;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.MainResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * @author 狐狸半面添
 * @create 2023-03-22 18:33
 */
@RestController
public class TestController {
    @Resource
    private RestHighLevelClient restHighLevelClient;

    /**
     * 用于测试是否连接 es 成功
     *
     * @return 返回 es 的基本信息,等价于访问:http://127.0.0.1:9200
     * @throws IOException 异常信息
     */
    @GetMapping("/getEsInfo")
    public Result getEsInfo() throws IOException {
        MainResponse info = restHighLevelClient.info(RequestOptions.DEFAULT);
        return Result.ok(info);
    }
}

浏览器访问:http://localhost:9999/getEsInfo

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

4.7 ⭐搜索服务

4.7.1 controller层

package com.fox.es.controller;

import com.fox.es.entity.Result;
import com.fox.es.service.ShareResourceSearchService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author 狐狸半面添
 * @create 2023-03-22 20:16
 */
@RestController
@RequestMapping("/search")
public class ShareResourceSearchController {

    @Resource
    private ShareResourceSearchService shareResourceSearchService;

    /**
     * 通过关键词获取数据列表
     *
     * @param keyWords 关键词
     * @param pageNo   页码
     * @param pageSize 每页大小
     * @return 数据列表,按照相关性从高到低进行排序
     */
    @GetMapping("/list")
    public Result list(@RequestParam("keyWords") String keyWords,
                       @RequestParam("pageNo") Integer pageNo,
                       @RequestParam("pageSize") Integer pageSize) {
        return shareResourceSearchService.list(keyWords, pageNo, pageSize);
    }
}

4.7.2 service接口层

package com.fox.es.service;

import com.fox.es.entity.Result;

/**
 * @author 狐狸半面添
 * @create 2023-03-22 20:18
 */
public interface ShareResourceSearchService {

    /**
     * 通过关键词获取数据列表
     *
     * @param keyWords 关键词
     * @param pageNo 页码
     * @param pageSize 每页大小
     * @return 数据列表,按照相关性从高到低进行排序
     */
    Result list(String keyWords, int pageNo, int pageSize);
}

4.7.3 service实现层

package com.fox.es.service.impl;

import com.alibaba.fastjson.JSON;
import com.fox.es.dto.BlogSimpleInfoDTO;
import com.fox.es.entity.Result;
import com.fox.es.service.ShareResourceSearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 狐狸半面添
 * @create 2023-03-22 20:18
 */
@Slf4j
@Service
public class ShareResourceSearchServiceImpl implements ShareResourceSearchService {
    @Resource
    private RestHighLevelClient restHighLevelClient;
    @Value("${elasticsearch.blog.index}")
    private String blogIndexStore;
    @Value("${elasticsearch.blog.source_fields}")
    private String blogFields;


    public Result list(String keyWords, int pageNo, int pageSize) {
        // 1.设置索引 - blog
        SearchRequest searchRequest = new SearchRequest(blogIndexStore);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 2.source源字段过虑
        String[] sourceFieldsArray = blogFields.split(",");
        searchSourceBuilder.fetchSource(sourceFieldsArray, new String[]{});

        // 3.关键字
        if (StringUtils.hasText(keyWords)) {
            // 哪些字段匹配关键字
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyWords, "title", "tags", "introduce", "content");
            // 设置匹配占比(表示最少匹配的子句个数,例如有五个可选子句,最少的匹配个数为5*70%=3.5.向下取整为3,这就表示五个子句最少要匹配其中三个才能查到)
            multiMatchQueryBuilder.minimumShouldMatch("70%");
            // 提升字段的Boost值
            multiMatchQueryBuilder.field("title", 10);
            multiMatchQueryBuilder.field("tags", 7);
            multiMatchQueryBuilder.field("introduce", 5);

            boolQueryBuilder.must(multiMatchQueryBuilder);
        }

        // 4.分页
        int start = (pageNo - 1) * pageSize;
        searchSourceBuilder.from(start);
        searchSourceBuilder.size(pageSize);

        // 布尔查询
        searchSourceBuilder.query(boolQueryBuilder);

        // 6.高亮设置
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        // 设置高亮字段
        ArrayList<HighlightBuilder.Field> fields = new ArrayList<>();
        fields.add(new HighlightBuilder.Field("title"));
        fields.add(new HighlightBuilder.Field("introduce"));
        highlightBuilder.fields().addAll(fields);
        searchSourceBuilder.highlighter(highlightBuilder);

        // 请求搜索
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("博客搜索异常:{}", e.getMessage());
            return Result.error(e.getMessage());
        }

        // 结果集处理
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        // 记录总数
        long totalHitsCount = hits.getTotalHits().value;
        // 数据列表
        List<BlogSimpleInfoDTO> list = new ArrayList<>();

        for (SearchHit hit : searchHits) {

            String sourceAsString = hit.getSourceAsString();
            // json 转 对象
            BlogSimpleInfoDTO blog = JSON.parseObject(sourceAsString, BlogSimpleInfoDTO.class);

            // 取出高亮字段内容
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields != null) {
                blog.setTitle(parseHighlightStr(blog.getTitle(), highlightFields.get("title")));
                blog.setIntroduce(parseHighlightStr(blog.getIntroduce(), highlightFields.get("introduce")));
            }

            list.add(blog);
        }

        // 封装信息返回前端
        HashMap<String, Object> resultMap = new HashMap<>(4);
        // 页码
        resultMap.put("pageNo", pageNo);
        // 每页记录数量
        resultMap.put("pageSize", pageSize);
        // 总记录数
        resultMap.put("total", totalHitsCount);
        // 该页信息
        resultMap.put("items", list);

        return Result.ok(resultMap);

    }

    public String parseHighlightStr(String text, HighlightField field) {
        if (field != null) {
            Text[] fragments = field.getFragments();
            StringBuilder stringBuilder = new StringBuilder();
            for (Text str : fragments) {
                stringBuilder.append(str.string());
            }
            return stringBuilder.toString();
        } else {
            return text;
        }
    }
}

这里我们使用 apipost7 进行测试:

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离

5.源码获取

这个demo如果你按照我的前三步进行了执行,那么直接运行源码应该是没有问题的。

源码地址:Mr-Write/SpringbootDemo: 各种demo案例 (github.com)

对应的是 elasticsearch-demo 包模块。

6.存在的问题与进阶说明

我们还存在另外一个需要解决的重要问题:与MySQL的数据一致性问题

❓ 为什么不直接使用ES存储所有的项目数据呢?

  • 非关系型表达,大量的反范式存储,导致维护基础数据异常(新增异常,修改异常,删除异常),需要MySQL做托底。
  • 不支持事务,一致性需要自己维护。
  • 从存储的角度来说,Elasticsearch是基于“字段”的,大行超多字段性能并不好。

数据同步的方式有很多种,比如通过ES的API进行增删改查,或者通过中间件像canalMQ进行数据全量、增量的同步。

springboot整合es搜索引擎,# java开发实战知识,elasticsearch,spring boot,搜索引擎,es,前后端分离
具体解决方案,可参考:docker环境安装mysql、canal、elasticsearch,基于binlog利用canal实现mysql的数据同步到elasticsearch中文章来源地址https://www.toymoban.com/news/detail-721260.html

到了这里,关于springboot整合es进行搜索的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot整合es进行搜索

    Elasticsearch 的官方地址:https://www.elastic.co/cn/ 这里选择下载 7.8.0 版本 下载地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch Elasticsearch 分为 Linux 和 Windows 版本,这里我们只是做测试,因此下载 windows 版本即可。 Windows 版的 Elasticsearch 的安装很简单,解压即安装完毕,解

    2024年02月08日
    浏览(40)
  • SpringBoot 整合 ES 进行各种高级查询搜索

    上一章:《ElasticSearch集群的搭建》 如果你还未安装es的相关信息,请先移步至:《ElasticSearch安装》进行安装 如果您的SpringBoot项目还未整合es,请移步至:《SpringBoot整合ElasticSearch实现模糊查询,批量CRUD,排序,分页,高亮》 同时本文的操作中涉及到ElasticSearchRepository和Ela

    2023年04月15日
    浏览(48)
  • 【分布式搜索引擎es】

    elasticsearch最擅长的是 搜索 和 数据分析 。 查询文档 常见的查询类型包括: 查询所有 :查询出所有数据,一般测试用。例如:match_all 全文检索(full text)查询 :利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如: match_query multi_match_query 精确查询 :根据精确

    2024年02月10日
    浏览(48)
  • 分布式搜索引擎ES

    elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 例如: 在GitHub搜索代码 在电商网站搜索商品 在百度搜索答案 ELK技术栈 elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应

    2024年02月04日
    浏览(41)
  • 详解最热门搜索引擎——ES

    ​ 互联网发展早期的时候,对于一般的公司储存的数据量不是那么的大,所以很多公司更倾向于使用数据库去存储和查询数据,如:现在去MySQL中查询数据,大概的查询方式就是:select * from table where filed like “%XXX%”或者其他方式,但是,如果我们在查询的时候没有用到或命

    2023年04月10日
    浏览(44)
  • RediSearch比Es搜索还快的搜索引擎

    RediSearch是一个Redis模块,为Redis提供查询、二次索引和全文搜索。要使用RediSearch,首先要在Redis数据上声明索引。然后可以使用重新搜索查询语言来查询该数据。RedSearch使用压缩的反向索引进行快速索引,占用内存少。RedSearch索引通过提供精确的短语匹配、模糊搜索和数字过

    2024年04月11日
    浏览(37)
  • Elasticsearch (ES) 搜索引擎: 搜索功能:搜索分页、搜索匹配、全文搜索、搜索建议、字段排序

    原文链接:https://xiets.blog.csdn.net/article/details/132348920 版权声明:原创文章禁止转载 专栏目录:Elasticsearch 专栏(总目录) ES 搜索 API 官网文档:Search APIs 先创建一个索引,并写入一些文档用于搜索示例: 写入一些文档示例: 官网API:The _source option 搜索结果中的文档数据封装

    2024年02月08日
    浏览(53)
  • 搜索引擎ES-RestHighLevelClient

    前言:本篇文章,主要讲述如何引入RestHighLevelClient,以及对其API的调用,属于入门级别的接口实用。适用于由于工作需要及时了解的童靴们以及初学者。想要了解ES底层更多内容的童鞋们,本篇文章并不适合 ! 前言:对比mysql,了解ES 首先通过图片对比我们了解的关系型数据

    2024年02月08日
    浏览(40)
  • 分布式搜索引擎es-3

    什么是聚合? 聚合 可以让我们极其方便的实现对数据的统计、分析、运算。例如: 什么 品牌 的手机最受欢迎? 这些手机的 平均 价格、 最高 价格、 最低 价格? 这些手机每 月的销售情况 如何? 实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实

    2024年02月07日
    浏览(44)
  • 分布式搜索分析引擎ES

    es是实时的分布式搜索分析引擎: 实时表现在新增到ES中的数据1s中就可以被检索到,这种新增数据对搜索的可见性成为“准实时搜索”。 分布式意味着可以动态调整集群规模,弹性扩容,支持上百个节点,相比 HDFS 等上千台的集群,更适合中等数据量的业务,不适合存储海

    2024年03月12日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包