ElasticSearch 学习笔记(四)-----ES在SpringBoot中的集成以及项目应用开发指南

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 接上一篇ElasticSearch 学习笔记(三)-----ES的设计原理以及分词器说明。今天我们主要介绍ES 与SpringBoot 的集成以及项目应用开发指南。

概述

接上一篇ElasticSearch 学习笔记(三)-----ES的设计原理以及分词器说明。今天我们主要介绍ES 与SpringBoot 的集成以及项目应用开发指南。

ES与SpringBoot的集成

添加依赖

此处,添加的依赖一定要与你安装的ES的版本对应,因为我安装的ES版本是 6.4.3。查询

ElasticSearch版本对应关系 发现对应的spring-data-elasticsearch 为 3.1.x

在SpringBoot 中对应依赖spring-boot-starter-data-elasticsearch 的版本为 2.1.1.RELEASE

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

创建文档

@Data
@Document(indexName = "titleindex",type = "_doc")
public class TitleDocument implements Serializable {
    /**
     *
     */
    @Id
    private Long id;
    /**
     *  选中ik 分词器
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String titlename;
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String description;
    public TitleDTO() {
    }
    public TitleDTO(Long id, String titlename, String description) {
        this.id = id;
        this.titlename = titlename;
        this.description = description;
    }
}

其中 indexName 与type 分别对应 索引名称和索引类型,如果类比于关系型数据库的话就相当于 库和表。在Spring Data 中每个文档必须要有id,不然数据会插入失败。同时还需要有缺省构造器,不然分页查询会报错。

@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")

@Field 注解作用到属性之上,上面代码表示的意思是,索引时分词使用 ik_max_word, 搜索时分词使用ik_smart

PS :

1、ik_max_word

会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。

2、ik_smart

会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。


Dao 层实现

@Component
public interface TitleRepository extends ElasticsearchRepository<TitleDTO,Long> {
}

此处我们直接继承了ElasticsearchRepository接口,该接口实现了 save ,deleteById,search 等方法,其中save 表示新增或者更新索引,deleteById表示删除索引,search表示查询索引数据。

Service 调用实现

@Autowired
    private TitleRepository titleRepository;
    /**
     * 创建索引
     * @param titlename
     * @param description
     */
    public void save(Long id,String titlename,String description) throws NoSuchAlgorithmException {
        TitleDocument titleDocument = new TitleDocument(id, titlename+id, description+id);
        titleRepository.save(titleDocument);
    }
    /**
     * 删除索引数据
     * @param id
     * @return
     */
    public boolean delete(Long id) {
        titleRepository.deleteById(id);
        return true;
    }
    /**
     * 查询所有的文章
     * @param searchContent
     * @return
     */
    public List<TitleDocument> getTitle(String searchContent) {
        QueryStringQueryBuilder builder = new QueryStringQueryBuilder(searchContent);
        System.out.println("查询的语句:"+builder);
        Iterable<TitleDocument> searchResult = titleRepository.search(builder);
        Iterator<TitleDocument> iterator = searchResult.iterator();
        List<TitleDocument> list=new ArrayList<>();
        while (iterator.hasNext()) {
            list.add(iterator.next());
        }
        return list;
    }
    /**
     * 分页查询
     * @param pageNumber
     * @param pageSize
     * @param searchContent
     * @return
     */
    public List<TitleDocument> pageTitle(Integer pageNumber, Integer pageSize, String searchContent) {
//        分页参数
        PageRequest pageRequest = PageRequest.of(pageNumber, pageSize);
        QueryStringQueryBuilder queryBuilder = new QueryStringQueryBuilder(searchContent);
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageRequest).withQuery(queryBuilder).build();
        System.out.println("查询的语句:" + searchQuery.getQuery().toString());
        Page<TitleDocument> search = titleRepository.search(searchQuery);
        return search.getContent();
    }

controller 调用实现

@RestController
public class TitleController {
    @Autowired
    private TitleService titleService;
    /**
     * 给索引添加数据
     * @return
     */
    @PostMapping("save")
    public String save(Long id,String titlename,String description) throws NoSuchAlgorithmException {
        titleService.save(id,titlename,description);
        return "success";
    }
    /**
     * 删除
     * @return
     */
    @PostMapping("delete")
    public String delete(Long id){
        titleService.delete(id);
        return  "success"  ;
    }
    @PostMapping("deleteDoc")
    public String deleteDoc(){
        titleService.deleteDoc();
        return  "success"  ;
    }
    @GetMapping("get")
    public List<TitleDocument> getTitle(String param) {
        List<TitleDocument> titleDocumentList = titleService.getTitle(param);
        return titleDocumentList;
    }
    @GetMapping("page")
    public List<TitleDocument> pageTitle(Integer pageNumber, Integer pageSize, String searchContent) {
        List<TitleDocument> documentList = titleService.pageTitle(pageNumber, pageSize, searchContent);
        return documentList;
    }

测试示例

@Test
    public void save() throws Exception {
        for (int i = 0; i < 20; i++) {
            titleService.save(Long.parseLong(String.valueOf(i)),"测试名称", "测试内容");
            System.out.println("插入第"+i+"条");
        }
    }

分页查询测试结果:

http://localhost:9898/page?pageNumber=0&pageSize=10&searchContent=测试


可能会遇到的几个问题

问题:安装好后Elasticsearch无法运行

解决:可能就是你版本安装错误了,注意版本一定要对应

问题:按照首页的方式调用Ik进行解析,但是无法设置mapping,出现如下错误

    analyzer [ik_max_word] not found for field 

解决:如果你的多个节点的集群,那么在集群的每个实例上都要安装Ik


项目应用开发指南

在项目的实际开发中我们一般遵循如下几个应用指南。

第一步,设计索引结构

首先我们需要考虑搜索的内容主体包含的信息,如ID,标题,描述,作者等,还需要考虑排序信息(如更新时间,创建时间)

第二步,为索引建立对应的模板(DTO)

如同上述demo 中设计的TitleDTO,字段与索引的字段一一对应,另外,因为key的名字都是定死的,为了统一管理,可以给每个key定义成final,方便统一管理和getset等。

第三步, 创建SearchService

该SearchService 主要有两个方法,

1、构建索引(创建,更新);

2、 删除索引

首先要一个ID作为唯一要构建的索引,通过ID从数据库中查询信息出来,包括需要关联的表等信息,得到模板数据(DTO),然后去elasticsearch 查询有没有该索引,如果没有则创建,如果有一条则更新,如果有多条则全部删除后重新创建。

第四步,当业务数据发生变化时更新索引信息,

当业务数据发生变化时候更新对应索引信息,分为两种形式调用

同步调用:直接在业务方法定点调用searchService对应的方法,

异步调用:基于消息中间件,如kafka,rabbitmq等。

编写搜索业务

当用户没有输入关键字的时候,默认直接从数据库查询信息,当用户输入关键词的时候先从es条件查询出数据的IDs,然后拿ids去数据库中取。

总结

本篇博客,我们首先通过一个demo 来熟悉了ES如何与SpringBoot 进行整合,当然这只是一个小小的demo,具体在项目中还涉及到ES 数据更mysql 数据的同步问题,接着我们还简单介绍了下ES在项目应用开发中的实践指南。

源代码

https://github.com/XWxiaowei/90-Java-demo-2/tree/master/course-21-elasticsearch/elasticsearch-demo

参考文献

SpringBoot整合ElasticSearch实现多版本的兼容

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
3天前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
9天前
|
存储 前端开发 Java
Spring Boot 集成 MinIO 与 KKFile 实现文件预览功能
本文详细介绍如何在Spring Boot项目中集成MinIO对象存储系统与KKFileView文件预览工具,实现文件上传及在线预览功能。首先搭建MinIO服务器,并在Spring Boot中配置MinIO SDK进行文件管理;接着通过KKFileView提供文件预览服务,最终实现文档管理系统的高效文件处理能力。
|
2天前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
13 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
2天前
|
前端开发 Java
学习SpringMVC,建立连接,请求,响应 SpringBoot初学,如何前后端交互(后端版)?最简单的能通过网址访问的后端服务器代码举例
文章介绍了如何使用SpringBoot创建简单的后端服务器来处理HTTP请求,包括建立连接、编写Controller处理请求,并返回响应给前端或网址。
8 0
学习SpringMVC,建立连接,请求,响应 SpringBoot初学,如何前后端交互(后端版)?最简单的能通过网址访问的后端服务器代码举例
|
13天前
|
网络协议 Java Maven
多模块项目使用ElasticSearch报错
多模块项目使用ElasticSearch报错
19 6
|
14天前
|
XML Java 关系型数据库
springboot 集成 mybatis-plus 代码生成器
本文介绍了如何在Spring Boot项目中集成MyBatis-Plus代码生成器,包括导入相关依赖坐标、配置快速代码生成器以及自定义代码生成器模板的步骤和代码示例,旨在提高开发效率,快速生成Entity、Mapper、Mapper XML、Service、Controller等代码。
springboot 集成 mybatis-plus 代码生成器
|
14天前
|
Java Spring
springboot 集成 swagger 2.x 和 3.0 以及 Failed to start bean ‘documentationPluginsBootstrapper‘问题的解决
本文介绍了如何在Spring Boot项目中集成Swagger 2.x和3.0版本,并提供了解决Swagger在Spring Boot中启动失败问题“Failed to start bean ‘documentationPluginsBootstrapper’; nested exception is java.lang.NullPointerEx”的方法,包括配置yml文件和Spring Boot版本的降级。
springboot 集成 swagger 2.x 和 3.0 以及 Failed to start bean ‘documentationPluginsBootstrapper‘问题的解决
|
1天前
|
jenkins Shell 持续交付
Jenkins持续集成GitLab项目 GitLab提交分支后触发Jenkis任务 持续集成 CI/CD 超级详细 超多图(一)
Jenkins持续集成GitLab项目 GitLab提交分支后触发Jenkis任务 持续集成 CI/CD 超级详细 超多图(一)
11 0
|
1天前
|
jenkins Shell 持续交付
Jenkins持续集成GitLab项目 GitLab提交分支后触发Jenkis任务 持续集成 CI/CD 超级详细 超多图(二)
Jenkins持续集成GitLab项目 GitLab提交分支后触发Jenkis任务 持续集成 CI/CD 超级详细 超多图(二)
10 0
|
1天前
|
自然语言处理 搜索推荐 Java
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(一)
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图
10 0