Elasticsearch 8.x 集成与 Java API 使用指南

目录

背景

版本区别

安装elaticsearch8.x服务

启动es服务

安装es管理平台

项目集成

pom.xml文件引入依赖

application.yml配置

ES初始化配置类实现

ES8.x常用API实现

1.判断es索引是否存在

2.删除索引

3.创建索引

4.新增文档

5.更新文档

6.根据id查询文档

7.根据id删除文档

8.查询文档列表

定义接口创建索引

定义业务方法

定义请求接口

操作接口


背景

随着 Elasticsearch 8.x 的发布,公司决定将现有的 Elasticsearch 7.x 版本升级到 8.x。然而,在升级过程中,我们发现许多 API 和功能发生了不兼容的变化,导致系统在迁移过程中遇到了大量问题。虽然官方文档提供了基本的操作指南,但实际应用中涉及的细节和调整却并未得到充分覆盖。为了帮助大家更顺利地过渡到 8.x,并有效应对这些变化, 本文将详细探讨 Elasticsearch 8.x 与 7.x 版本之间的主要差异,特别是在 Java 开发中的实际应用与迁移问题。

版本区别

依赖差异

  • 版本7.x以及更早之前版本依赖
<dependency>
  <groupId>org.elasticsearch</groupId>
  <artifactId>elasticsearch</artifactId>
  <version>7.x.x</version>
</dependency>
<dependency>
  <groupId>org.elasticsearch.client</groupId>
  <artifactId>elasticsearch-rest-high-level-client</artifactId>
  <version>7.x.x</version>
</dependency>
  • 8.x版本依赖
<dependency>
  <groupId>co.elastic.clients</groupId>
  <artifactId>elasticsearch-java</artifactId>
  <version>8.x.x</version>
</dependency>

安全性增强 :与 7.x 的默认无安全配置不同,8.x 默认启用安全功能,包括用户认证、授权、TLS 加密等,给开发者带来了更多的配置和管理任务。

查询和聚合优化:某些查询接口和聚合方法发生了变化,特别是对于大规模数据集的支持和性能提升方面有了显著进步,但这些变化需要开发者重新调整代码实现。

安装elaticsearch8.x服务

本文试例在window系统本地安装服务

启动es服务

elaticsearch版本为:8.16

官方下载地址:Past Releases of Elastic Stack Software | Elastic

百度云网盘:百度网盘 请输入提取码 提取码: 92h6

下载完解压目录如下

进入config目录修改yml文件

因为8.x版本默认开启权限校验以及ssl证书校验,为了方便后续使用,这里只保留权限校验,关闭ssl证书校验

进入bin目录执行cmd打开命令行重置登录密码

.\elasticsearch-reset-password -u elastic

默认账号:elastic

记得保存好密码,以免遗忘

进入bin目录双击elasticsearch.bat启动es服务

安装es管理平台

  1. 可自行安装es官方面板:kibana
  2. 本文使用的是google浏览器插件:Multi Elasticsearch Heads(可在google插件市场下载)

打开插件并连接es服务

连接成功

项目集成

这里通过集成在spring boot项目中来了解es8.x的配置连接以及api的使用

注:虽然基于springboot,但是我们这里不使用spring boot data提供的es集成依赖

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

因为data只提供了一些es简单操作的api,对于复杂的只有通过script手写DSL语句来完成,扩展性和维护性都不是很好,对不熟悉DSL语句的也很不友好,所以我们还是选择使用原生依赖 elasticsearch-java

可下载博主github源码参考:GitHub - RemainderTime/spring-boot-base-demo: 拿来即用springboot基础框架项目

pom.xml文件引入依赖

<!-- elasticsearch8.x 搜索引擎 -->
<dependency>
  <groupId>co.elastic.clients</groupId>
  <artifactId>elasticsearch-java</artifactId>
  <version>8.16.0</version>
</dependency>

application.yml配置

elasticsearch:
  host: localhost
  port: 9200
  username: elastic
  password: 8wVPrsP=9vlQWHBuHniH  #window系统本地启动 es8.x 重置密码命令:.\elasticsearch-reset-password -u elastic

ES初始化配置类实现

@Component
public class EsConfig {

    @Value("${elasticsearch.host}")
    private String elasticsearchHost;
    @Value("${elasticsearch.port}")
    private int elasticsearchPort;
    @Value("${elasticsearch.username}")
    private String username;
    @Value("${elasticsearch.password}")
    private String password;

    /**
     -最大连接数 (maxConnTotal):设置总的最大连接数,取决于业务的并发量。500-2000 之间较为合理。
     -每个节点的最大连接数 (maxConnPerRoute):控制每个节点的最大连接数,建议 50-100 之间。
     -IO 线程数 (setIoThreadCount):根据 CPU 核心数设置,通常为 2-4 倍 CPU 核心数。
     -连接超时、套接字超时、获取连接超时:一般设置为 10-30 秒,复杂查询或大数据量操作可适当增加到 20-60 秒。
     -失败监听器 (setFailureListener):自定义重试和故障处理逻辑,确保高可用性。
     */
    @Bean
    public ElasticsearchClient elasticsearchClient() {
        // 创建凭证提供者
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
            AuthScope.ANY,
            new UsernamePasswordCredentials(username, password)
        );
        // 自定义 RestClientBuilder 配置
        RestClientBuilder restClientBuilder = RestClient.builder(
            new HttpHost(elasticsearchHost, elasticsearchPort, "http")
        ).setHttpClientConfigCallback(httpClientBuilder ->
                                      httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider) // 配置认证信息
                                     );
        // 配置连接超时、套接字超时、获取连接超时
        restClientBuilder.setRequestConfigCallback(builder ->
                                                   builder.setConnectTimeout(20000)
                                                   .setSocketTimeout(20000)
                                                   .setConnectionRequestTimeout(20000)
                                                  );
        // 创建 RestClientTransport 和 ElasticsearchClient
        RestClient restClient = restClientBuilder.build();
        ElasticsearchTransport transport = new RestClientTransport(
            restClient,
            new JacksonJsonpMapper() // 使用 Jackson 进行 JSON 处理
        );
        return new ElasticsearchClient(transport);
    }
}

ES8.x常用API实现

先创建一个全局es工具类

@Slf4j
@Component
public class EsUtil {
    public static ElasticsearchClient esClient;
    {
        esClient = (ElasticsearchClient) ApplicationContextUtils.getBean("elasticsearchClient");
    }
    /...
}

下面罗列工具类中实现的常用的操作方法。

1.判断es索引是否存在
public static boolean existIndex(String indexName) {
        try {
            // 创建 ExistsRequest 请求
            ExistsRequest request = new ExistsRequest.Builder()
                    .index(indexName)
                    .build();
            // 发送请求并获取响应
            BooleanResponse response = esClient.indices().exists(request);
            // 返回索引是否存在
            return response.value();
        } catch (Exception e) {
            // 处理异常
            e.printStackTrace();
            return false;
        }
    }
2.删除索引
@SneakyThrows
public static void delIndex(String indexName) {
    if (existIndex(indexName)) {
        return;
    }
    esClient.indices().delete(d -> d.index(indexName));
}
3.创建索引
public static void createIndex(String indexName) {
    if (existIndex(indexName)) {
        throw new RuntimeException("索引已经存在");
    }
    try {
        CreateIndexResponse createIndexResponse = esClient.indices().create(c -> c.index(indexName));
        // 处理响应
        if (createIndexResponse.acknowledged()) {
            log.info(" indexed create successfully.");
        } else {
            log.info("Failed to create index.");
        }
    } catch (Exception e) {
        // 捕获异常并打印详细错误信息
        e.printStackTrace();
        throw new RuntimeException("创建索引失败,索引名:" + indexName + ",错误信息:" + e.getMessage(), e);
    }
}
4.新增文档
public static boolean addDocument(EsBaseModel esBaseModel) {
    try {
        // 创建 IndexRequest 实例
        IndexRequest request = new IndexRequest.Builder()
        .index(esBaseModel.getIndexName())
        .id(esBaseModel.getDocumentId()) //指定文档id,不指定会自动生成
        .document(esBaseModel.getDocumentModel())
        .opType(OpType.Create) // 只会在文档 ID 不存在时创建文档
        .build();
    
        IndexResponse response = esClient.index(request);
        if ("created".equals(response.result())) {
            log.info("Document created: " + response.id());
            return true;
        } else {
            log.info("Document already exists or failed to create.");
            return false;
        }
    } catch (Exception e) {
        log.error("es新增文档失败", e);
        e.printStackTrace();
    }
    return false;
}
5.更新文档
public boolean updateDocument(EsBaseModel esBaseModel) {
    try {
        UpdateRequest updateRequest = new UpdateRequest.Builder<>()
        .index(esBaseModel.getIndexName())
        .id(esBaseModel.getDocumentId())
        .doc(esBaseModel.getDocumentModel()).build();
        UpdateResponse updateResponse = esClient.update(updateRequest, esBaseModel.getClazz());
        log.info("Document updated: " + updateResponse.id());
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}
6.根据id查询文档
public static <T> T getDocumentById(EsBaseModel esBaseModel) {
    try {
        GetRequest getRequest = new GetRequest.Builder()
        .index(esBaseModel.getIndexName())
        .id(esBaseModel.getDocumentId())
        .build();
        GetResponse<T> getResponse = esClient.get(getRequest, esBaseModel.getClazz());
        if (getResponse.found()) {
            return getResponse.source();
        }
    } catch (Exception e) {
        log.error("es列表查询失败", e);
    }
    return null;
}
7.根据id删除文档
public static Boolean deleteDocumentById(EsBaseModel esBaseModel) {
    try {
        DeleteRequest deleteRequest = new DeleteRequest.Builder()
        .index(esBaseModel.getDocumentId())
        .id(esBaseModel.getDocumentId())
        .build();
        DeleteResponse deleteResponse = esClient.delete(deleteRequest);
        if ("deleted".equals(deleteResponse.result())) {
            log.info("Document deleted: " + deleteResponse.id());
            return true;
        } else {
            log.info("Document delete failed: " + deleteResponse.id());
            return false;
        }
    } catch (Exception e) {
        log.error("es列表删除失败", e);
    }
    return false;
}
8.查询文档列表
public static <T> List<T> getDocumentList(EsSearchModel searchModel) {
    List<T> eslist = new ArrayList<>();
    try {
        SearchResponse<T> search = esClient.search(buildSearchRequest(searchModel), searchModel.getClazz());
        if (Objects.isNull(search)) {
            return eslist;
        }
        HitsMetadata<T> hits = search.hits();
        if (Objects.isNull(hits)) {
            return eslist;
        }
        List<Hit<T>> sourceHitList = hits.hits();
        if (CollectionUtils.isEmpty(sourceHitList)) {
            return eslist;
        }
        sourceHitList.forEach(item -> {
            // 处理每个命中
            eslist.add(item.source());
        });
        return eslist;
    } catch (Exception e) {
        log.error("es列表查询失败", e);
    }
    return eslist;
}

注意!!!由于方法太多,文中就不一一列举,想了解更多方法可下载上面博主提供的github地址进行下载项目并找到EsUtil.class类查看,里面有更多场景的使用方法和api详解

定义接口创建索引

定义业务方法
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public RetObj syncEs(Long userId) {
        User user = userMapper.selectById(userId);
        if (Objects.isNull(user)) {
            return RetObj.error("用户不存在");
        }
        String index = StringUtil.camelToKebabCase(user.getClass().getSimpleName());
        if (!EsUtil.existIndex(index)) {
            EsUtil.createIndex(index);
        }
        EsUtil.addDocument(new EsBaseModel(index, String.valueOf(user.getId()), user, user.getClass()));
        return RetObj.success();
    }

    @Override
    public RetObj getEsId(Long userId) {
        Object user = EsUtil.getDocumentById(new EsBaseModel("user", String.valueOf(userId), null, User.class));
        if(Objects.nonNull(user)){
            return RetObj.success(user);
        }
        return RetObj.error("es中不存在该用户");
    }
}
定义请求接口
@RestController(value = "用户控制器")
@RequestMapping("/user")
@Tag(name = "用户控制器")
public class UserController {

    @Autowired
    private UserService userService;

    @Operation(summary = "es同步用户信息", description = "用户信息")
    @GetMapping("/syncEs")
    public RetObj syncEs(Long userId){
        return userService.syncEs(userId);
    }

    @Operation(summary = "es查询用户信息", description = "用户信息")
    @GetMapping("/getEsId")
    public RetObj getEsId(Long userId){
        return userService.getEsId(userId);
    }
}
操作接口

请求接口插入一条数据到索引中

查看面板发现自动创建了一个user索引

查询user索引中的数据存在一条

请求接口查询es数据


至此对于Elaticsearch8.x版本的学习完成了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/939599.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EfficientNet模型Pytorch版本具体实现

EfficientNet模型原理&#xff1a;EfficientNet&#xff1a;对模型深度、宽度和分辨率的混合缩放策略-CSDN博客 一、激活函数&#xff1a; EfficientNet模型使用了Swish激活函数而不是更常见的Relu激活函数 1、公式定义 Swish(x) x * sigmoid(x)是一个平滑的非线性激活函数…

Git连接远程仓库(超详细)

目录 一、Gitee 远程仓库连接 1. HTTPS 方式 2. SSH公钥方式 &#xff08;1&#xff09;账户公钥 &#xff08;2&#xff09;仓库公钥 仓库的 SSH Key 和账户 SSH Key 的区别&#xff1f;​ 二、GitHub远程仓库连接 1. HTTPS方式 2.SSH公钥方式 本文将介绍如何通过 H…

AutoMQ 流表一体新特性 Table Topic 发布: 无缝集成 AWS S3 Table 和 Iceberg

超越共享存储&#xff1a;使用 Apache Iceberg 中的 AutoMQ Table Topic 实现流处理与分析的统一 自 2023 年底官宣以来&#xff0c;AutoMQ 成功地将 Apache Kafka 从“Shared Nothing architecture”转变为“Shared Storage architecture”&#xff0c;这为京东、知乎、小红书…

Upload-labs 靶场(通关攻略)

WebShell 一句话木马: <?php eval($_POST[a])?> <?php system($_POST[a])?> 第一关&#xff08;删除前端js校验&#xff09; 删除return checkFile() 就能上传成功 第二关(抓包文件类型校验) BP抓包修改后缀 改为2.php后放行 第三关(上传php同种类型的不…

Linux —— 管理进程

一、查看进程 运行态&#xff08;Running&#xff09; 定义&#xff1a;处于运行态的进程正在 CPU 上执行指令。在单 CPU 系统中&#xff0c;同一时刻只有一个进程处于运行态&#xff1b;在多 CPU 或多核系统中&#xff0c;可能有多个进程同时处于运行态。示例&#xff1a; 当…

Linux脚本语言学习--下

4.Bash的变量 4.1.用户自定义变量 4.1.1.什么是变量 变量是计算机内存的单元&#xff0c;其中存放的值可以改变。当Shell脚本需要保存一些信息的时候&#xff0c;如一个文件名或是一个数字&#xff0c;就把他存放在一个变量中。每个变量有一个名字&#xff0c;所以很容易引用…

武汉市电子信息与通信工程职称公示了

2024年武汉市电子信息与通信工程专业职称公示了&#xff0c;本次公示通过人员有109人。 基本这已经是今年武汉市工程相关职称最后公示了&#xff0c;等待出证即可。 为什么有人好奇&#xff0c;一样的资料&#xff0c;都是业绩、论文等&#xff0c;有的人可以过&#xff0c;有的…

ModelScope-Agent(3):docker启动

目录 前两篇并没有使用到docker,但我看项目中是有docker配置的&#xff0c;不过没有在教程中写出来。学习了ragflow的docker配置流程之后&#xff0c;试一下modelscope-agent的配置。 先创建model-scope的cuda环境 conda create --name modelscope-agent python3.10 conda acti…

如何高效获取Twitter数据:Apify平台上的推特数据采集解决方案

引言 在数据分析和市场研究领域&#xff0c;Twitter&#xff08;现在的X&#xff09;数据一直是重要的信息来源。但是&#xff0c;自从Twitter更改API定价策略后&#xff0c;获取数据的成本大幅提升。本文将介绍一个经济实惠的替代方案。 为什么需要Twitter数据&#xff1f; …

MySql 中的解决某列中多个字段查询是否存在指定某个值, FIND_IN_SET 用法。

简言&#xff1a;今天公司数据库里面有个列是多个数据拼接而成的比如&#xff1a;**“,131113,749932833,749932825,749932826,749932827,749932828,749932829,”**想要通过sql 查找749932833值的列&#xff0c;很多同学第一想到的就是like 模糊匹配&#xff0c;模糊匹配不能保…

go引用包生成不了vendor的问题

比如我要引入github.com/jinzhu/gorm这个包. 1. 首先获取包 go get github.com/jinzhu/gorm 这时go.mod文件中也有这个包依赖信息了. 2. 然后构建vendor go mod vendor 结果发现vendor目录下没有生成对应的包, 而且modules.txt也注释掉这个包了. 原因是没有其进行引用, go…

基于 SSM 框架 Vue 电脑测评系统:引领电脑评测新方向

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

知识分享第三十天-力扣343.(整数拆分)

343 整数拆分 给定一个正整数 n&#xff0c;将其拆分为至少两个正整数的和&#xff0c;并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: 输入: 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: 10 输出: 36 解释: 10 3 3 4, 3 3 4 36。 说明: 你可…

Nginx常用配置详解(1)

Nginx常用配置详解 一、全局块&#xff08;main&#xff09;配置 在Nginx的配置文件中&#xff0c;最外层的部分是全局块。这部分配置通常会影响Nginx服务器整体的运行参数。 worker_processes 作用&#xff1a;这个配置指令用于指定Nginx工作进程的数量。工作进程是Nginx处理…

力扣2300.咒语和药水的成功对数(二分法)

根据 灵茶山艾府 题解所写 题目描述&#xff1a; 给你两个正整数数组 spells 和 potions &#xff0c;长度分别为 n 和 m &#xff0c;其中 spells[i] 表示第 i 个咒语的能量强度&#xff0c;potions[j] 表示第 j 瓶药水的能量强度。 同时给你一个整数 success 。一个咒语和药…

电商大数据的几种获取渠道分享!

在当今数字化时代&#xff0c;电商大数据已成为企业决策和运营的重要基础。如何高效地获取、分析和利用这些数据&#xff0c;对于提升电商企业的竞争力至关重要。本文将详细介绍几种电商大数据的获取渠道&#xff0c;帮助电商从业者更好地掌握数据资源&#xff0c;提升业务洞察…

CQRS Design Pattern in Microservices - CQRS模式

原文链接 CQRS Design Pattern in Microservices - GeeksforGeeks 【文章看起来像是AI写的。。。 &#x1f602;&#x1f602;&#x1f602;】 简介 实现步骤 1&#xff0c;识别有界上下文&#xff1a;&#xff08;Identify Bounded Contexts:&#xff09; 2&#xff0c;命…

c语言----选择结构

基本概念 选择结构是C语言中用于根据条件判断来执行不同代码块的结构。它允许程序在不同的条件下执行不同的操作&#xff0c;使程序具有决策能力。 if语句 单分支if语句 语法格式&#xff1a; if (条件表达式) { 执行语句块; } 功能&#xff1a; 当条件表达式的值为真&#…

RK3588 , mpp硬编码rgb, 保存MP4视频文件.

RK3588 , mpp硬编码yuv, 保存MP4视频文件. ⚡️ 传送 ➡️ RK3588, FFmpeg 拉流 RTSP, mpp 硬解码转RGBRk3588 FFmpeg 拉流 RTSP, 硬解码转RGBUbuntu x64 架构, 交叉编译aarch64 FFmpeg mppCode Init MppMPP_RET init_mpp

uniapp blob格式转换为video .mp4文件使用ffmpeg工具

前言 介绍一下这三种对象使用场景 您前端一旦涉及到文件或图片上传Q到服务器&#xff0c;就势必离不了 Blob/File /base64 三种主流的类型它们之间 互转 也成了常态 Blob - FileBlob -Base64Base64 - BlobFile-Base64Base64 _ File uniapp 上传文件 现在已获取到了blob格式的…