SpringBoot整合ElasticSearch

马臻
2023-12-01

ElasticSearch是一个基于Lucene的分布式、高扩展、高实时的搜索与数据分析引擎。一般我们用来作为网站全文搜索。

为了方便理解,可以类比到关系型数据库中的概念进行对比,如下表:

关系型数据库Elasticsearch
Databases(数据库)Indices(索引)
Tables(表)Types(类型)
Rows(行)Documents(文档)
Columns(列)Fields(字段)

Elasticsearch包含多个索引(indices)(数据库),每个索引可以包含多个类型(types)(表),每个类型包含多个文档(documents)(行),每个文档包含多个字段(Fields)(列)。

1、导入jar

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

2、下载安装

1、下载

windows下安装 elasticsearch

2、安装

1.解压下载的压缩包

2.运行Elasticsearch 双击运行 elasticsearch-2.4.4\bin 目录下的 elasticsearch.bat 文件。

3.访问Elasticsearch浏览器访问 http://localhost:9200。(默认使用9200端口)

3、下载插件

为便于管理Elasticsearch,安装 head 插件可实现可视化管理。

cd F:\es\elasticsearch-6.4.3\bin
elasticsearch-plugin install mobz/elasticsearch-head

访问head插件:浏览器中访问 http://localhost:9200/_plugin/head/

es5 以上版本安装 head 需要安装 node 和 grunt(之前的直接用 plugin 命令即可安装)

1、下载安装 node

2、执行 npm install -g grunt-cli 安装 grunt ,安装完成后执行 grunt -version 查看是否安装成功,会显示安装的版本号

3、在该链接下载文件 https://github.com/mobz/elasticsearch-head/archive/master.zip

4、下载完成后解压到 elasticsearch 安装目录,使用 cmd 进入该目录下执行 npm install , 等待安装完成…

F:\es\elasticsearch-6.4.3\elasticsearch-head-master>npm install

5、安装完成后执行 grunt server 或者 npm run start 运行 head 插件,如果不成功重新安装 grunt。

成功如下

F:\es\elasticsearch-6.4.3\elasticsearch-head-master>npm run start

> elasticsearch-head@0.0.0 start F:\es\elasticsearch-6.4.3\elasticsearch-head-master
> grunt server

Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://localhost:9100

6、访问该地址即可:http://localhost:9100

4、安装服务

本地的 Elasticsearch 运行起来了,但生产环境每次都这样启动,未免过于麻烦且不安全。最好的方式是把 Elasticsearch 加入到 Windows 服务中(Service),每次开机自动后台启动。

打开cmd命令行:

cd F:\es\elasticsearch-6.4.3\bin
elasticsearch-service.bat install
elasticsearch-service.bat start

3、安装 ik 中文分词

1、安装对应版本的 elasticsearch-analysis-ik,版本 https://github.com/medcl/elasticsearch-analysis-ik/

2、将下载的压缩包,在 plugins 文件夹下进行解压

4、整合配置

1、配置

SpirngBoot 自动完成了以下配置:

  • 完成 Client 节点信息 clusterNodes:clusterName:用于连接ES节点;
  • 完成 ElasticsearchTemplate:用于对ES进行数据映射;
  • 编写了一个 ElasticsearchRepository 的子接口,用于操作ES的CRUD;
spring:
	data:
      elasticsearch:
        #配置ElasticSearch节点名称
        cluster-name: elasticsearch
        #注: 9300 是 Java 客户端的端口。9200 是支持 Restful HTTP 的接口。
        cluster-nodes: localhost:9300
        # 使用jpa命名规范
        repositories:
          enabled: true

2、绑定实体

package com.manster.search.model;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.io.Serializable;
import java.util.Date;

/**
 * @Author manster
 * @Date 2022/5/20
 **/
@Data
@Document(indexName = "blog", type = "blog", createIndex = true)
public class BlogDocument implements Serializable {

    @Id
    private Long id;
    // 中文分词器
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String title;

    private Long authorId;
    @Field(type = FieldType.Keyword)
    private String authorName;
    private String authorAvatar;

    private Long categoryId;
    @Field(type = FieldType.Keyword)
    private String categoryName;

    private Boolean recommend;
    private Integer level;

    private Integer commentCount;
    private Integer viewCount;

    @Field(type = FieldType.Date)
    private Date created;

}
  • @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") 表示使用 ik 分词器
  • @Field(type = FieldType.Keyword) 表明这是一个关键字分词,不需要进行切分分词

3、基础jpa

package com.manster.search.repository;

import com.manster.search.model.BlogDocument;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

/**
 * @Author manster
 * @Date 2022/5/20
 **/
@Repository
public interface BlogRepository extends ElasticsearchRepository<BlogDocument, Long> {

}

初始化数据

    //初始化上传数据
    @Override
    public int initEsData(List<BlogVo> records) {
        if(records == null || records.isEmpty()){
            return 0;
        }

        List<BlogDocument> documents = new ArrayList<>();
        //转换对象
        for (BlogVo record : records) {
            BlogDocument blogDocument = new BlogDocument();
            BeanUtils.copyProperties(record, blogDocument);
            documents.add(blogDocument);
        }
        //存入es
        blogRepository.saveAll(documents);
        return documents.size();
    }

进行查找

package com.manster.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.manster.search.model.BlogDocument;
import com.manster.search.repository.BlogRepository;
import com.manster.service.SearchService;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

/**
 * @Author manster
 * @Date 2022/5/20
 **/
@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    BlogRepository blogRepository;

    @Override
    public IPage search(Page page, String keyword) {
        // mp 的 page 转为 jpa 的 page
        Long current = page.getCurrent() - 1;   //jpa中的分页从0开始
        Long size = page.getSize();
        Pageable pageable = PageRequest.of(current.intValue(), size.intValue());

        //es 得到 page
        MultiMatchQueryBuilder builder = QueryBuilders.multiMatchQuery(keyword, "title", "authorName", "categoryName");
        org.springframework.data.domain.Page<BlogDocument> documents = blogRepository.search(builder, pageable);

        // jpa 的 page 转为 mybatis-plus的 page
        IPage pageData = new Page(page.getCurrent(), page.getSize(), documents.getTotalElements());
        pageData.setRecords(documents.getContent());

        return pageData;
    }
}

至此我们就可以进行全局的查找了

 类似资料: