ElasticSearch8 - SpringBoot整合ElasticSearch

前言

springboot 整合 ES 有两种方案,ES 官方提供的 Elasticsearch Java API Client 和 spring 提供的 [Spring Data Elasticsearch](Spring Data Elasticsearch)

两种方案各有优劣

Spring:高度封装,用着舒服。缺点是更新不及时,有可能无法使用 ES 的新 API

ES 官方:更新及时,灵活,缺点是太灵活了,基本是一比一复制 REST APIs,项目中使用需要二次封装。

Elasticsearch Java API Client

目前最新版本 ES8.12,要求 jdk8 以上,API 里面使用了大量的 builder 和 lambda

官方也提供了 测试用例

兼容

翻了不少博客,大部分都是使用 High Level Rest Client,这是旧版本的 api,新版本使用 Elasticsearch Java API Client,如何兼容旧版本,官方也提供了解决方案)

下文描述的均是新版 API

添加 jar 包

官方文档:[installation](安装| Elasticsearch Java API 客户端 [8.12] |松紧带 — Installation | Elasticsearch Java API Client [8.12] | Elastic)

使用的是 maven,在 pom.xml 中添加

<dependency>  <groupId>co.elastic.clients</groupId>  <artifactId>elasticsearch-java</artifactId>  <version>8.12.2</version>  
</dependency><!-- 如果有添加springmvc,此包可不引入 -->
<dependency>  <groupId>com.fasterxml.jackson.core</groupId>  <artifactId>jackson-databind</artifactId>  <version>2.12.3</version>  
</dependency>

如果报错 ClassNotFoundException: jakarta.json.spi.JsonProvider,则还需要添加

<dependency><groupId>jakarta.json</groupId><artifactId>jakarta.json-api</artifactId><version>2.0.1</version>
</dependency>

打印请求

在 application. yml 中添加配置,打印 es 的 http 请求(建议在开发调试时使用)

logging:  level:  tracer: TRACE

连接 ES

配置文件如下,后续所有 ES 操作都通过 ElasticsearchClient 对象

更多配置请看 Common configuration

@Configuration  
public class ElasticSearchConfig {  @Bean  public ElasticsearchClient esClient() {  // ES服务器URL  String serverUrl = "http://127.0.0.1:9200";  // ES用户名和密码  String userName = "xxx";  String password = "xxx";  BasicCredentialsProvider credsProv = new BasicCredentialsProvider();  credsProv.setCredentials(  AuthScope.ANY, new UsernamePasswordCredentials(userName, password)  );  RestClient restClient = RestClient  .builder(HttpHost.create(serverUrl))  .setHttpClientConfigCallback(hc -> hc.setDefaultCredentialsProvider(credsProv))  .build();  ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());  return new ElasticsearchClient(transport);  }  }

索引操作

代码中的 esClient 就是 ElasticsearchClient,请自行注入 bean

// 索引名字  
String indexName = "student";  // 索引是否存在  
BooleanResponse books = esClient.indices().exists(e -> e.index(indexName));  
System.out.println("索引是否存在:" + books.value());  // 创建索引  
esClient.indices().create(c -> c  .index(indexName)  .mappings(mappings -> mappings  // 映射  .properties("name", p -> p  .text(t -> t // text类型,index=false  .index(false)  )  )  .properties("age", p -> p  .long_(t -> t) // long类型  )  )  
);  // 删除索引  
esClient.indices().delete(d -> d.index(indexName));

文档操作 (CRUD)

下文以官方测试数据 account. json 为例

实体类

首先定义实体类,用于 ES 中的字段

public class Account {private String id;// 解决ES中字段与实体类字段不一致的问题  @JsonProperty("account_number")private Long account_number;  private String address;  private Integer age;  private Long balance;  private String city;  private String email;  private String employer;  private String firstname;  private String lastname;  private String gender;  private String state;  ... 省略get、set方法
}

新增

String indexName = "account";  // 索引名字
Account account = new Account();
account.setId("1");
account.setLastname("guyu");   // 新增
CreateResponse createResponse = esClient.create(c -> c  .index(indexName) // 索引名字  .id(account.getId()) // id  .document(account) // 实体类  
);

修改

UpdateResponse<Account> updateResp = esClient.update(u -> u  .index(indexName)  .id(account.getId())  .doc(account),  Account.class  
);

删除

DeleteResponse deleteResp = esClient.delete(d -> d.index(indexName).id("1"));

批量新增

批量操作需要使用到 bulk

List<Account> accountList = ...
BulkRequest.Builder br = new BulkRequest.Builder();  
for (Account acc : accountList) {  br.operations(op -> op  .create(c -> c  .index(indexName)  .id(acc.getId())  .document(acc)  )  );  
}  
BulkResponse bulkResp = esClient.bulk(br.build());

有没有觉得批量新增的 .create () 里面的参数很眼熟,批量删除和更新请举一反三

根据 id 查询

// 定义实体类
GetResponse<Account> getResp = esClient.get(g -> g.index(indexName).id("1"), Account.class);  
if (getResp.found()) {  Account source = getResp.source();  // 这就是得到的实体类source.setId(getResp.id());  
}// 不定义实体类
GetResponse<ObjectNode> getResp = esClient.get(g -> g  .index(indexName)  .id("1"),  ObjectNode.class  
);  
if (getResp.found()) {  ObjectNode json = getResp.source();  String firstname = json.get("firstname").asText();  System.out.println(firstname);  
}

搜索

搜索全部

SearchResponse<Account> searchResp = esClient.search(s -> s  .index(indexName)  .query(q -> q.matchAll(m -> m))  // 搜索全部, Account.class  
);HitsMetadata<Account> hits = searchResp.hits();  
long totalValue = hits.total().value(); // 匹配到的数量  
hits.hits().forEach(h -> {  Account acc = h.source(); // 这就是得到的实体类  acc.setId(h.id());  
});

ES API 的对象定义,基本与返回的 json 一一对应的,所以 SearchResponse 就不过多赘述。

搜索 firstname = Amber

SearchResponse<Account> searchResp = esClient.search(s -> s  .index(indexName)  .query(q -> q  // 查询  .match(t -> t  .field("firstname")  .query("Amber")  )  )  , Account.class  
);// 也可以这样写
Query firstNameQuery = MatchQuery.of(m -> m.field("firstname").query("Amber"))._toQuery();
SearchResponse<Account> searchResp = esClient.search(s -> s  .index(indexName)  .query(firstNameQuery)  , Account.class  
);

嵌套查询,比如搜索 firstname = Amber AND age = 32

Query firstNameQuery = MatchQuery.of(m -> m.field("firstname").query("Amber"))._toQuery();  
Query ageQuery = MatchQuery.of(m -> m.field("age").query(32))._toQuery();  SearchResponse<Account> searchResp = esClient.search(s -> s  .index(indexName)  .query(q -> q  .bool(b -> b.must(firstNameQuery, ageQuery))  )  , Account.class  
);

浅分页

from 和 size 参数类似于 mysql 的 limit,详细说明见 Paginate search results

SearchResponse<Account> searchResp = esClient.search(s -> s  .index(indexName)   .from(0)  // 分页参数.size(20)  // 分页参数, Account.class  
);

排序

SearchResponse<Account> searchResp = esClient.search(s -> s  .index(indexName)   .sort(so -> so  // 排序字段1.field(f -> f  .field("age")  .order(SortOrder.Asc)  )  )  .sort(so -> so  // 排序字段2.field(f -> f  .field("account_number")  .order(SortOrder.Desc)  )  )  , Account.class  
);

Spring Data Elasticsearch

文档: Spring Data Elasticsearch

添加 jar 和配置

pom.xml添加依赖

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

yml 配置

spring:  elasticsearch:  uris: http://xxx:9200  username: xxx  password: xxx
logging:  level:  # 输出es的查询参数(调试用)tracer: TRACE  

索引操作

实体类

@Data  
@Document(indexName = "account")  
public class Account {  @Id  private String id;  // 解决ES中字段与实体类字段不一致的问题  @Field(name = "account_number", type = FieldType.Long)  private Long accountNumber;  @Field(type = FieldType.Text)  private String address;  @Field(type = FieldType.Integer)  private Integer age;  @Field(type = FieldType.Long)  private Long balance;  @Field(type = FieldType.Text)  private String city;  @Field(type = FieldType.Text)  private String email;  @Field(type = FieldType.Text)  private String employer;  @Field(type = FieldType.Text)  private String firstname;  @Field(type = FieldType.Text)  private String lastname;  @Field(type = FieldType.Text)  private String gender;  @Field(type = FieldType.Text)  private String state;  ... 省略get、set 方法
}
IndexOperations idxOpt = template.indexOps(Account.class);  
// 索引是否存在  
boolean idxExist = idxOpt.exists();  // 创建索引  
boolean createSuccess = idxOpt.createWithMapping();  
System.out.println(createSuccess);  // 删除索引  
boolean deleted = idxOpt.delete();

文档操作(CRUD)

Account account = new Account();  
account.setId("1");  
account.setLastname("guyu");  // 这是插入或覆盖,如果id存在了就是覆盖  
template.save(account);  // 修改,用的是es的_update  
template.update(account);// 删除  
template.delete(account)// 批量新增(用的是es的_bulk)
List<Account> accountList = ...
template.save(accountList);// 根据id查询
Account account = template.get("1", Account.class);

搜索 + 排序 + 分页

// 搜索 firstname = Amber AND age = 32
Criteria criteria = new Criteria();  
criteria.and(new Criteria("firstname").is("Amber"));  
criteria.and(new Criteria("age").is(32));  // 分页  
int pageNum = 1; // 页码  
int pageSize = 20; // 每页数量  
Query query = new CriteriaQueryBuilder(criteria)  .withSort(Sort.by(new Order(Sort.Direction.ASC, "age"))) // 排序字段1  .withSort(Sort.by(new Order(Sort.Direction.DESC, "balance"))) // 排序字段1  .withPageable(PageRequest.of(pageNum - 1, pageSize)) // 浅分页  // 不需要查询的字段.withSourceFilter(new FetchSourceFilterBuilder().withExcludes("email", "address").build()).build();  SearchHits<Account> searchHits = template.search(query, Account.class);  
long totalValue = searchHits.getTotalHits(); // 匹配到的数量  
for (SearchHit<Account> searchHit : searchHits.getSearchHits()) {  Account account = searchHit.getContent(); // 这就是得到的实体类  
}

总结

本文介绍了 SpringBoot 整合 ElasticSearch 的两种方案,但均只是简单提及,更详细的用法需要自行查看官方文档。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV的图像颜色空间转换、缩放、裁剪与旋转

OpenCV的图像颜色空间转换 一、引言 在数字图像处理中&#xff0c;颜色空间转换是一个常见的操作。OpenCV作为一个强大的计算机视觉库&#xff0c;提供了丰富的函数来支持颜色空间转换。本文将围绕OpenCV的颜色空间转换展开&#xff0c;帮助读者理解颜色空间的基本概念、转换…

如何使用Windows电脑部署Lychee私有图床网站并实现无公网IP远程管理本地图片

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-MSVdVLkQMnY9Y2HW {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

NB-IOT——浅谈NB-IOT及模块测试

浅谈NB-IOT及模块基本使用测试 介绍什么是NB-IOT&#xff1f;NB-IOT的特点 使用准备基本使用 总结 介绍 什么是NB-IOT&#xff1f; NB-IoT&#xff0c;即窄带物联网&#xff08;Narrowband Internet of Things&#xff09;&#xff0c;是一种低功耗广域物联网&#xff08;LPW…

MongoDB Atlas维护指南:常见类型、注意事项与窗口设置

为了给Atlas用户更好的产品体验&#xff0c;MongoDB产品团队会进行定期维护。 本文将会介绍&#xff1a; 常见维护项目种类及频率&#xff0c;注意事项维护期间的影响及建议维护窗口设置说明维护告警设置和邮件通知范例 维护窗口常见项目 定期SSL证书轮换软件升级&#xff…

Golang生成UUID

安装依赖 go get -u github.com/google/uuid示例 函数签名func NewV7() ( UUID ,错误) uid : uuid.NewV7()

.htaccess配置重写url引擎

.htaccess 文件配置 Apache&#xff1a; <IfModule mod_rewrite.c>Options FollowSymlinks -Indexes -MultiviewsRewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-dRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^(.*)$ index.php?s/$1 [QSA,PT,L] </IfModu…

Java八股文(数据结构)

Java八股文の数据结构 数据结构 数据结构 请解释以下数据结构的概念&#xff1a;链表、栈、队列和树。 链表是一种线性数据结构&#xff0c;由节点组成&#xff0c;每个节点包含了指向下一个节点的指针&#xff1b; 栈是一种后进先出&#xff08;LIFO&#xff09;的数据结构&a…

SqlAlchemy学习总结

1 安装 pip install sqlalchemy 2 创建Engine 2.1 数据库连接协议&#xff1a; SQLite: sqlite:///./mydb.db "sqlite:///:memory:"(内存型) MySQL: mysql://username:passwordhostname/database_name PostgreSQL: postgresql://username:passwordhostname/databas…

Mac添加和关闭开机应用

文章目录 mac添加和关闭开机应用添加开机应用删除/查看 mac添加和关闭开机应用 添加开机应用 删除/查看 打开&#xff1a;系统设置–》通用–》登录项–》查看登录时打开列表 选中打开项目&#xff0c;点击“-”符号

loopvar 改动不同版本的影响-基础循环

示例代码 package mainimport ("fmt""runtime" )func main() {fmt.Println("golang version:", runtime.Version())for i : 0; i < 10; i {fmt.Println(&i)} }代码说明 这个代码先打印了使用的golang的版本&#xff0c;然后进行一个for…

华为防火墙配置指引超详细(包含安全配置部分)以USG6320为例

华为防火墙USG6320 华为防火墙USG6320是一款高性能、高可靠的下一代防火墙,适用于中小型企业、分支机构等场景。该防火墙支持多种安全功能,可以有效抵御网络攻击,保护网络安全。 目录 华为防火墙USG6320 1. 初始配置 2. 安全策略配置 3. 防火墙功能配置 4. 高可用性配…

论文笔记:分层问题-图像共注意力问答

整理了2017 Hierarchical Question-Image Co-Attention for Visual Question Answering&#xff09;论文的阅读笔记 背景模型问题定义模型结构平行共注意力交替共注意力 实验可视化 背景 视觉问答(VQA)的注意力模型在此之前已经有了很多工作&#xff0c;这种模型生成了突出显示…

词令关键词口令直达工具:打开「词令」输入关键词直达口令怎么使用?

词令是一款关键词口令直达工具&#xff1b;使用词令关键词口令直达工具&#xff0c;输入指定的词令关键词直达口令&#xff0c;搜索直达该词令关联的网站、页面、程序、应用、服务或功能等等&#xff0c;实现一键直达目标&#xff0c;避免繁琐的查找点击行为&#xff0c;提高用…

axios发送get请求但参数中有数组导致请求路径多出了“[]“的处理办法

一、情况 使用axios发送get请求携带了数组参数时&#xff0c;请求路径中就会多出[]字符&#xff0c;而在后端也会报错 二、解决办法 1、安装qs 当前项目的命令行中安装 npm install qs2、引入qs库(使用qs库来将参数对象转换为字符串) // 全局 import qs from qs Vue.proto…

事件穿透效果

讲述一下事件穿透的需求&#xff0c;大家可以根据实际情况来考虑是否采用这种方式来制作页面&#xff0c;&#xff08;项目中遇到了底部是地图&#xff0c;两侧面板&#xff0c;但是UI在设计的时候为了好看&#xff0c;会有很大的遮罩阴影部分&#xff0c;如果按照时间制作会导…

[BT]BUUCTF刷题第10天(3.28)

第10天&#xff08;共3题&#xff09; Basic BUU SQL COURSE 1 打开网站看到右上角有个登录界面&#xff0c;怀疑是SQL注入 但是多次尝试都无果 通过看题解知道了还有一个隐藏网页&#xff08;content_detail.php&#xff09; 随便点一个测试新闻进去后点F12看网络&#xf…

C#实现身份证格式验证(自建异常实现提醒)

基本信息 中国居民身份证的格式包括18位数字&#xff0c;这些数字分别代表不同的信息&#xff1a; 第1、2位数字表示省份代码。 第3、4位数字表示城市代码。 第5、6位数字表示区县代码。 第7至14位数字表示出生年、月、日&#xff08;其中7、8、9、10位是年&#xff0c;11、12…

git2consul+consul+gitlab连接

前提&#xff1a;安装好了gitlab和部署好了consul集群。使用git2consul连接持续检测gitlab仓库变化。 提交相关配置到gitlab中->git2consul连接gitlab,得到变化的配置 -> git2consul将变化的配置同步到consul中->后端服务器从consul中的key/value中得到变化的配置 1、…

如何使用群晖WebDAV实现固定公网地址同步Zotero文献管理器

文章目录 前言1. Docker 部署 Trfɪk2. 本地访问traefik测试3. Linux 安装cpolar4. 配置Traefik公网访问地址5. 公网远程访问Traefik6. 固定Traefik公网地址 前言 Trfɪk 是一个云原生的新型的 HTTP 反向代理、负载均衡软件&#xff0c;能轻易的部署微服务。它支持多种后端 (D…

ODCC春季全会召开|忆联持续5年以领先技术为ODCC项目研究提供支持

2024开放数据中心委员会&#xff08;ODCC&#xff09;春季全会于3月27日-29日在江西省上饶市召开&#xff0c;作为长期的合作伙伴&#xff0c;忆联应邀参加本次会议&#xff0c;并在新技术与测试工作组会议上就研究课题开展了汇报与讨论。 2024开放数据中心委员会&#xff08;O…