Springboot整合原生ES依赖

server/2024/12/27 3:00:44/

前言

Springboot整合依赖大概有三种方式:

  • es原生依赖:elasticsearch-rest-high-level-client
  • Spring Data Elasticsearch
  • Easy-es

三者的区别

1. Elasticsearch Rest High Level Client

简介:

  • 这是官方提供的 Elasticsearch 客户端,支持 Java 应用程序与 Elasticsearch 集群进行通信。

特点:

  • 低级别 API: 提供对 Elasticsearch 的低级别 REST API 封装,允许开发者直接使用 Elasticsearch 的所有功能。
  • 灵活性: 可以执行所有 Elasticsearch 支持的操作,如索引、搜索、更新和删除等。
  • 直接的控制: 开发者可以手动构造请求和处理响应,提供了更大的控制权。
  • 与 Elasticsearch 版本保持同步: 由于是官方客户端,可以更好地与 Elasticsearch 版本进行兼容。

使用场景:

  • 适合需要精细控制和高灵活性的应用,特别是在处理复杂的查询或需要使用 Elasticsearch 的高级特性时。

2. Spring Data Elasticsearch

简介:

  • 这是 Spring 生态系统中的一部分,旨在简化使用 Elasticsearch 的过程,提供了更高层次的抽象。

特点:

  • 集成 Spring: 提供与 Spring 框架的无缝集成,支持依赖注入、配置和自动化管理。
  • Repository 模式: 使用类似于 Spring Data JPA 的 Repository 接口,可以更方便地执行 CRUD 操作和查询。
  • 实体映射: 支持将 Java 对象直接映射到 Elasticsearch 文档,简化了数据的处理。
  • 注解支持: 通过注解定义索引、字段和查询,减少了样板代码。

使用场景:

  • 适合已经在使用 Spring 的应用程序,特别是希望快速实现与 Elasticsearch 的集成,同时享受 Spring 提供的便利。

3. Easy-ES

简介:

  • Easy-ES 是一个第三方的 Java 客户端库,旨在简化 Elasticsearch 的操作,提供更为便捷的 API。

特点:

  • 简化 API: 封装了 Elasticsearch 的复杂性,使得操作更简单易用,尤其是在批量操作和查询时。
  • 注解驱动: 提供了注解来配置索引和字段,使得使用更加直观。
  • 支持多种数据源: 除了支持 Elasticsearch 外,还能与其他数据源进行集成。
  • 灵活配置: 提供了多种配置选项,方便用户定制化。

使用场景:

  • 适合需要简化 Elasticsearch 操作的开发者,特别是在处理简单应用或快速开发时,能够提高开发效率。

总结

  • Elasticsearch Rest High Level Client: 提供全面的 API 访问,适合需要直接控制和高灵活性的场景。
  • Spring Data Elasticsearch: 适合与 Spring 应用集成,简化数据访问的同时保持 Spring 风格。
  • Easy-ES: 更加简化的 API,适合快速开发和简单应用,特别适合对 Elasticsearch 操作不太熟悉的开发者。

Elasticsearch Rest High Level Client整合

1、添加依赖

 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.3.2</version></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.3.2</version></dependency><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.3.2</version></dependency><!-- ...其他依赖省略 具体可以才看源码 -->

2、属性类添加

EsProperties

主要用于读取yaml文件的配置

package com.walker.es.properites;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@ConfigurationProperties(prefix = "es")
@Component
@Data
public class EsProperties {private String host;private Integer port;private String scheme;private EsSecurityProperites security;
}
package com.walker.es.properites;import lombok.Data;@Data
public class EsSecurityProperites {private String username;private String password;private boolean enable;
}

3、application.yaml配置添加

根据自己的es配置进行修改,

这里添加了账号密码配置,一般来说,配置一下安全一些,否则容易被攻击

es:host: localhostport: 19200scheme: http
#  配置账号密码security:enable: trueusername: elasticpassword: elastic

4、ES配置类

主要用于创建RestHighLevelClient类,该类是es的客户端工具类,方法都集成在该类中

package com.walker.es.config;import com.walker.es.properites.EsProperties;
import com.walker.es.properites.EsSecurityProperites;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Slf4j
@Configuration
public class EsConfig {@Autowiredprivate EsProperties esProperties;//    注入restHighLevelClient到bean中@Beanpublic RestHighLevelClient restHighLevelClient(){//        构建es客户端RestClientBuilder builder = RestClient.builder( new HttpHost(esProperties.getHost(),esProperties.getPort(), esProperties.getScheme()));// 是否需要开启账号密码验证EsSecurityProperites security = esProperties.getSecurity();if(security!=null&&security.isEnable()){log.info("es~开启账号密码验证!");BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(security.getUsername(), security.getPassword()));builder.setHttpClientConfigCallback(httpClientBuilder ->httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));}log.info("构建RestHighLevelClient:{}",esProperties);return new RestHighLevelClient(builder);}
}

5、测试验证

实体类

package com.walker.es.model;import lombok.Data;@Data
public class AlarmRecordEntity {
//    事件private String title;
//    设备private String deviceCode;
//    时间private String time;//    索引名称public static String getIndex(){return "alarms";}}

controller类

主要有下面的接口方法

创建索引
  • 直接执行新增client.index(indexRequest, RequestOptions.DEFAULT); 也可以创建索引,但是直接创建的索引,字段的配置就都是默认的,例如我们如果需要使用中文分词器,就需要重新创建索引,这个在生产环境来说是比较麻烦的,需要迁移数据
  • 索引可以单独写一个接口去创建索引,指定好字段的属性。
@PostMapping("/createIndex")public String createIndex() {CreateIndexRequest request = new CreateIndexRequest(AlarmRecordEntity.getIndex());//        设置别名request.alias(new Alias("alias_alarm"));// 设置索引的设置(可选)request.settings(Settings.builder().put("number_of_shards", 3)  // 分片数量.put("number_of_replicas", 2) // 副本数量.put("analysis.tokenizer.ik_max_word.type", "ik_max_word") // 使用 ik_max_word 分词器);// 使用 HashMap 创建映射Map<String, Object> properties = new HashMap<>();Map<String, Object> titleField = new HashMap<>();titleField.put("type", "text");titleField.put("analyzer", "ik_max_word"); // 配置中文分词器properties.put("title", titleField);Map<String, Object> deviceCodeField = new HashMap<>();deviceCodeField.put("type", "keyword");properties.put("deviceCode", deviceCodeField);Map<String, Object> timeField = new HashMap<>();timeField.put("type", "date");properties.put("time", timeField);// 设置映射HashMap<String, Object> map = new HashMap<>();map.put("properties", properties);request.mapping(map);try {client.indices().create(request, RequestOptions.DEFAULT);return "Index created successfully";} catch (IOException e) {e.printStackTrace();return "Error creating index: " + e.getMessage();}}

调用后:

在kibana中可以看到

  • 可以看到分片,副本等数量,以及存储的大小、别名等

  • 别名的作用也是很大的,如果后面索引太大,然后使用日期等配置索引的时候,就有作用了

  • mapping 映射 字段的类型,以及分词器

es的字段类型主要有以下这些:

1. 基本数据类型
String: 以前用于文本和关键词。现在使用以下两种类型替代:text: 用于全文搜索,支持分词。
keyword: 用于精确匹配,不支持分词,适合用于过滤、排序和聚合。
Numeric Types:integer: 整数类型(32位)。
long: 长整数类型(64位)。
float: 单精度浮点数(32位)。
double: 双精度浮点数(64位)。
short: 短整型(16位)。
byte: 字节类型(8位)。
Date: 日期类型,支持多种日期格式。2. 布尔类型
boolean: 布尔类型,只能取值 truefalse3. 复杂数据类型
Object: 嵌套的 JSON 对象,可以包含其他字段。Nested: 嵌套对象,支持对嵌套文档的查询,保持对象之间的关联性。4. 特殊类型
geo_point: 地理坐标类型,存储经纬度信息。geo_shape: 用于存储复杂的地理形状数据(如多边形等)。ip: 存储 IP 地址。5. 二进制类型
binary: 存储二进制数据,支持 Base64 编码的内容。
6. 列表类型
Elasticsearch 也支持字段的数组形式,可以将多个值存储在同一个字段中
增加单条记录
// 增加单条报警记录@PostMapping("/createAlarm")public String createAlarm(@RequestBody AlarmRecordEntity alarmRecord) throws IOException {IndexRequest indexRequest = new IndexRequest(AlarmRecordEntity.getIndex()).source("title", alarmRecord.getTitle(),"deviceCode", alarmRecord.getDeviceCode(),"time", alarmRecord.getTime());
//        创建单条数据 使用indexclient.index(indexRequest, RequestOptions.DEFAULT);return "Alarm record created";}
  • 使用index增加单条数据
  • 如果使用执行该index的时候,索引不存在,则会自己创建索引,例如将index改为alarms222,则可以看到执行的结果

但是他的配置使用的都是默认的

批量增加
    // 批量增加报警记录@PostMapping("/bulk")public String bulkCreateAlarms(@RequestBody List<AlarmRecordEntity> alarmRecords) throws IOException {//        批量增加数据 使用bulk方法BulkRequest bulkRequest = new BulkRequest();for (AlarmRecordEntity alarmRecord : alarmRecords) {IndexRequest indexRequest = new IndexRequest(AlarmRecordEntity.getIndex()).source("title", alarmRecord.getTitle(),"deviceCode", alarmRecord.getDeviceCode(),"time", alarmRecord.getTime());bulkRequest.add(indexRequest);}BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);if (bulkResponse.hasFailures()) {return "Failed to create some alarm records: " + bulkResponse.buildFailureMessage();}return "Batch alarm records created successfully";}

使用bulk插入多条数据

至于修改、删除、查询单个记录等,便不在多说,可以查看源码并进行调用

搜索
@PostMapping("/search")public ResponseEntity<List<AlarmRecordEntity>> searchAlarms(@RequestBody AlarmSearchRequest request) {try {// 创建搜索请求SearchRequest searchRequest = new SearchRequest(AlarmRecordEntity.getIndex());SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();// 分词查询if (StrUtil.isNotBlank(request.getTitle())) {sourceBuilder.query(QueryBuilders.matchQuery("title", request.getTitle()));}//            精确查询if(StrUtil.isNotBlank(request.getDeviceCode()))  {sourceBuilder.query(QueryBuilders.termQuery("deviceCode", request.getDeviceCode()));}// 时间范围查询(假设时间字段是一个日期格式)if (StrUtil.isNotBlank(request.getStartTime())) {sourceBuilder.query(QueryBuilders.rangeQuery("time").gte(request.getStartTime()).lte(request.getEndTime()));}// 将构建好的查询条件放入搜索请求中searchRequest.source(sourceBuilder);// 执行搜索SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);// 解析搜索结果List<AlarmRecordEntity> alarms = new ArrayList<>();response.getHits().forEach(hit -> {AlarmRecordEntity alarm = new AlarmRecordEntity();alarm.setTitle((String) hit.getSourceAsMap().get("title"));alarm.setDeviceCode((String) hit.getSourceAsMap().get("deviceCode"));alarm.setTime((String) hit.getSourceAsMap().get("time"));alarms.add(alarm);});return ResponseEntity.ok(alarms); // 返回 200 状态和报警记录列表} catch (Exception e) {return ResponseEntity.status(500).body(null); // 返回 500 状态和错误信息}}
  • 验证一下是否会分词

请求参数

{"title": "打架"
}

搜索结果

  • deviceCode精确查询
{"title": "","deviceCode": "A001","startTime": "","endTime": ""
}

返回结果:

  • 时间范围
{"title": "","deviceCode": "","startTime": "2024-10-20","endTime": "2024-10-25"
}

返回结果:

总结

大概先做这些演示,不过在实际的过程中,使用原生的es依赖可能也不是最优选,因为会有很多字段需要手打,而不是直接方法获取

所以后面会演示使用spring封装的es依赖,以及easy-es的整合,敬请期待!

源码

https://gitee.com/shen-chuhao/walker_open_java.git


http://www.ppmy.cn/server/137309.html

相关文章

微信小程序 setData数据量过大的解决与分页加载的实现

我们经常使用setData方法来修改数据&#xff0c;从而达到更新页面的目的。但是当我们通过setData方法设置的数据过大时就会报如下错误。 vdSyncBatch 数据传输长度为 2260792 已经超过最大长度 1048576这是因为setData设置的数据量是有限制的&#xff0c;单次设置的数据大小不…

更改Unity项目使用的.NET版本

c#中报错信息 too many root set 更改Unity项目使用的.NET版本 1、Unity编辑器中&#xff0c;点击菜单Edit -> Project Setting -> Player 2、找到Scripting Runtime Version* 选择对应的.NET 版本 PS: 要在Unity 2021中将Api Compatibility Level更改为.NET 4.x&…

微信小程序中关闭默认的 `navigationBar`,并使用自定义的 `nav-bar` 组件

要在微信小程序中关闭默认的 navigationBar&#xff0c;并使用自定义的 nav-bar 组件&#xff0c;你可以按照以下步骤操作&#xff1a; 1. 关闭默认的 navigationBar 在你的页面的配置文件 *.json 中设置 navigationBar 为 false。你需要在页面的 JSON 配置文件中添加以下代码…

IDE 使用技巧与插件推荐

IDE 使用技巧与插件推荐 在现代软件开发中&#xff0c;集成开发环境&#xff08;IDE&#xff09;是开发者不可或缺的工具。一个功能强大的 IDE 能够帮助开发者在编写、调试和维护代码时&#xff0c;提高效率和代码质量。本文将深入探讨一些常用的 IDE 使用技巧&#xff0c;以及…

LeetCode LCP 28. 采购方案

LeetCode LCP 28. 采购方案 小力将 N 个零件的报价存于数组 nums。小力预算为 target&#xff0c;假定小力仅购买两个零件&#xff0c;要求购买零件的花费不超过预算&#xff0c;请问他有多少种采购方案。 注意&#xff1a;答案需要以 1e9 7 (1000000007) 为底取模&#xff0c…

SQLite3库增删改查实现数据管理

1. SQLite3简介 SQLite3是一个轻量级的、嵌入式的关系型数据库管理系统&#xff0c;在保存测序数据或结果等时可使用&#xff0c;简单高效&#xff0c;并且有无需服务器、单文件存储数据、支持标准SQL、支持跨平台等优势。 本文以Sqlite3数据库为基础&#xff0c;创建代码示例…

17. 从尾到头打印链表

文章目录 QuestionIdeasCode Question 输入一个链表的头结点&#xff0c;按照 从尾到头 的顺序返回节点的值。 返回的结果用数组存储。 数据范围0≤链表长度 ≤1000。 样例 输入&#xff1a;[2, 3, 5] 返回&#xff1a;[5, 3, 2] Ideas 直接遍历链表&#xff0c;然后倒序…

STATCOM静止同步补偿器原理及MATLAB仿真模型

STATCOM原理简述 整个STATCOM 装置相当于一个电压大小可以控制的电压源。当控制 STATCOM 装置产生的电压小于系统电压即UI<US 时&#xff0c;STATCOM 装置向系统输出的无功功率Q<0&#xff0c;此时 STATCOM 装置相当于电感&#xff1b;当控制 STATCOM 装置产生的电压大于…