Elasticsearch (简称ES) 是一个基于 Lucene 的分布式、高扩展、高实时的搜索与数据分析引擎。本章介绍 Spring Boot 应用集成 Elasticsearch ,通过 Spring 封装的API访问 Elasticsearch 。

Spring Data Elasticsearch 是 Spring Data 子项目,提供对 Elasticsearch 集成与访问的支持。需要注意的是 Spring Data Elasticsearch 版本 3.2.x 与 4.x 不兼容,在升级 Spring Boot 版本时要做好评估。本章是以 Spring Data Elasticsearch 4.x 为基础。

依赖

引入 Spring Data Elasticsearch

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

Spring Data Elasticsearch 3.x 只兼容到 Elasticsearch 6.x,Elasticsearch 7.x 需要使用Spring Data Elasticsearch 4.x 版本。这是由于 Spring Data Elasticsearch 依赖 ES 官方客户端,而 ES 在大版本之间提供的 Client 有部分不能兼容。所以在选择版本时最好和 ES 服务器版本一至。

如果使用 Rest Client 需要引入 spring-web ,否则会报 java.lang.ClassNotFoundException: org.springframework.http.HttpHeaders

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

配置

在 application.yml 加上

spring:elasticsearch:rest:connection-timeout: 1s # 连接超时时间username: # 连接用户名password: # 连接密码read-timeout: 30s # 读取超时时间uris: ${ES_HOST:localhost}:${ES_PORT:9200} # es rest 接口地址,多个用逗号隔开

创建 ElasticsearchRestTemplate

@Configuration
@EnableElasticsearchRepositories
public class ElasticsearchConfiguration extends AbstractElasticsearchConfiguration {@Value("${spring.elasticsearch.rest.uris}")private String uris;@Override@Beanpublic RestHighLevelClient elasticsearchClient() {final ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo(uris.split(",")).withConnectTimeout(Duration.ofSeconds(5)).withSocketTimeout(Duration.ofSeconds(30)).build();return RestClients.create(clientConfiguration).rest();}@Bean("esRestTemplate")public ElasticsearchRestTemplate esRestTemplate() {return new ElasticsearchRestTemplate(elasticsearchClient());}}

@EnableElasticsearchRepositories注解可使用 JPA 访问 ES ,basePackages 为 Spring 扫描的包
该段代码配置 Elasticsearch Client ,创建 ElasticsearchRestTemplate 对象。

配置完可在任意地方注入使用 ElasticsearchRestTemplate

@Autowired
private ElasticsearchRestTemplate esRestTemplate;

使用

Spring Data Elasticsearch 对 ES 官方客户端API进行封装,访问 ES 更简单。

ElasticsearchTemplate
ElasticsearchOperations 使用 Transport Client 的接口的实现。从 4.0 版开始不推荐,请改用 ElasticsearchRestTemplate 。

ElasticsearchRestTemplate
ElasticsearchOperations 使用高级REST客户端的接口的实现。

ReactiveElasticsearchTemplate
响应式,默认的实现 ReactiveElasticsearchOperations 。

本章使用 ElasticsearchRestTemplate ,以前面代码配置为例,创建了 ElasticsearchRestTemplate 对象,下面例举一些用代码实现 KQL 语句功能。

  • 定义 LogEntity 类
package com.engrz.lab.springboot.elasticsearch;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.time.LocalDateTime;/*** @author Engr-Z* @since 2021/2/5*/
@Document(indexName = "demo-log")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LogEntity {@Idprivate String id;/*** 日志等级*/@Field(type = FieldType.Keyword)private String level;/*** 日志标题*/@Field(type = FieldType.Text)private String title;/*** 日志内容*/@Field(type = FieldType.Text)private String content;/*** 记录时间*/@Field(type = FieldType.Date, format = DateFormat.date_time)private LocalDateTime recordTime;
}

@Document 注解用来声明对应 ES 中一个文档, indexName 是索引名
每个字段可用 @Field 注解声明类型

  • 插入
String id = UUID.randomUUID().toString().replaceAll("-", "");
LogEntity logEntity = new LogEntity(id, "info", "新增", "插入一条数据", LocalDateTime.now());
esRestTemplate.save(logEntity);
  • 修改
Document doc = Document.create();
doc.put("level", "warn");
doc.put("recordTime", LocalDateTime.now());
UpdateQuery.Builder builder = UpdateQuery.builder("6cba54cbc56a49cc8deee516e18b0121").withDocument(doc);
UpdateQuery updateQuery = builder.build();
esRestTemplate.update(updateQuery, IndexCoordinates.of("demo-log"))

指定修改文档id

  • 删除
esRestTemplate.delete("6cba54cbc56a49cc8deee516e18b0121", IndexCoordinates.of("demo-log"))
  • 查询

因为没有建立索引,以下查询条件字段加上 .keyword 关键字。关于 Elasticsearch KQL 相关的知识会单独讲解

  1. 需求描述:查询日志总数

KQL:

GET demo-log/_count

JAVA:

NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
long count = esRestTemplate.count(searchQueryBuilder.build(), IndexCoordinates.of("demo-log"));
log.info("count -> {}", count);
  1. 需求描述:查找3天以内,级别为 error 的日志,按记录时间倒序,分页,取前20条

KQL:

GET demo-log/_search
{"query": {"bool": {"must": [{"term": {"level": "error"}},{"range": {"recordTime.keyword": {"gte": "2021-02-05T10:00:00","format": "yyyy-MM-dd HH:mm:ss"}}}]}},"sort": [{"recordTime.keyword": {"order": "desc"}}],"size": 20
}

JAVA:

BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();// 查询日志级别为 error 的
boolQueryBuilder.must().add(new TermQueryBuilder("level.keyword", "error"));// 查询3天内数的数据
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("recordTime.keyword");
rangeQueryBuilder.gte(LocalDateTime.now().minusDays(3));
boolQueryBuilder.must().add(rangeQueryBuilder);// 分页查询20条
PageRequest pageRequest = PageRequest.of(0, 20, Sort.by("recordTime.keyword").descending());NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
searchQueryBuilder.withQuery(boolQueryBuilder).withPageable(pageRequest);Query searchQuery = searchQueryBuilder.build();
SearchHits<LogEntity> hits = esRestTemplate.search(searchQuery, LogEntity.class);
List<SearchHit<LogEntity>> hitList = hits.getSearchHits();
log.info("hit size -> {}", hitList.size());
hitList.forEach(hit -> {log.info("返回数据:", hit.getContent().toString());
});

ES 查询默认最多返回10000条数据,超过10000条需要修改 ES 设置或使用滚动查询。 ES 分页方式会用新的章节讲解

  1. 需求描述:按日志级别分组,打印出每个级别的日志数

KQL:

GET demo-log/_search
{"aggs": {"termLevel": {"terms": {"field": "level.keyword"}}}
}

JAVA:

TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("aggTerms").field("level.keyword");NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
searchQueryBuilder.addAggregation(termsAggregationBuilder);Query searchQuery = searchQueryBuilder.build();
SearchHits<LogEntity> hits = esRestTemplate.search(searchQuery, LogEntity.class);
Terms aggTerms = hits.getAggregations().get("aggTerms");
for (Terms.Bucket bucket : aggTerms.getBuckets()) {log.info("level={}, count={}", bucket.getKey(), bucket.getDocCount());
}

AggregationBuilders 类可以创建其他类型的聚合查询,如 AggregationBuilders.sum 计数

整合JPA

我们也可以通过 Spring JPA 访问 ES ,使操作 ES 和访问数据库一样简单。使用 JPA 需要使用 @EnableElasticsearchRepositories 注解,前面在配置的时候有说明。

创建 LogRepository 接口,继承 ElasticsearchRepository


public interface LogRepository extends ElasticsearchRepository<LogEntity, String> {}

Spring Boot 会自动扫描并装配,在代码中直接注入使用。

@Autowired
private LogRepository logRepository;

通过继承 ElasticsearchRepository 接口, LogRepository 拥有常用的方法。

  • 插入
String id = UUID.randomUUID().toString().replaceAll("-", "");
LogEntity logEntity = new LogEntity(id, "info", "JPA新增", "JPA插入一条数据", LocalDateTime.now());
logRepository.save(logEntity);
  • 修改

未提供。更新数据要重建索引, ES 中不建议大量更新数据。

  • 删除
logRepository.deleteById("cd5c2ac848724acf8d66522e743eed87");
  • 计数
long count = logRepository.count();
log.info("count -> {}", count);
  • 查询

根据id查找:

Optional<LogEntity> entity = logRepository.findById("b64446b58492454c8576504b68767332");
log.info("size -> {}", entity.orElse(null));
  • 自定义条件

Spring JPA 支持把条件写在方法名中,无需手动编写实现方法,框架自动按规则解析。

  1. 需求描述:分页查询指定日志级别数据
List<LogEntity> findByLevel(String level, Pageable pageable);

在 Repository 中的方法如果有 Pageable 参数, Spring 会自动使用 pageable 中的参数信息实现分页和排序。
方法名中支持 and、or、like等查询,也支持lt、gt、lte、gte、eq等比较。可参考官方列表Query creation

KQL 查询

虽然 Spring JPA 支持多个条件查询,但如果条件比较多,方法名会很长。可以使用 @Query 注解传入 KQL 查询

  1. 需求描述:分页查询指定日志级别数据,并支持时间段查询
@Query("{\n" +"    \"bool\": {\n" +"      \"must\": [\n" +"        {\n" +"          \"term\": {\n" +"            \"level\": ?0\n" +"          }\n" +"        },\n" +"        {\n" +"          \"range\": {\n" +"            \"recordTime.keyword\": {\n" +"              \"gte\": ?1,\n" +"              \"lte\": ?2\n" +"            }\n" +"          }\n" +"        }\n" +"      ]\n" +"    }\n" +"  }")
List<LogEntity> exampleQuery(String level, LocalDateTime startDateTime, LocalDateTime endDateTime, Pageable pageable);

一般场推荐JPA,复杂的查询还是需要ElasticsearchRestTemplate。两者结合使用会更高效简洁。


除非注明,否则均为"攻城狮·正"原创文章,转载请注明出处。
本文链接:https://engr-z.com/190.html

Spring Boot 集成 Elasticsearch相关推荐

  1. 第 4-8 课:Spring Boot 集成 ElasticSearch

    ElasticSearch 是⼀个开源的搜索引擎,建⽴在⼀个全⽂搜索引擎库 Apache Lucene™ 基础之上. Lucene 可以说是当下最先进.⾼性能.全功能的搜索引擎库--⽆论是开源还是私有 ...

  2. Spring Boot 集成 Elasticsearch 实战

    今天讲解下如何使用 Spring Boot 结合 ES. 可以在 ES 官方文档中发现,ES 为 Java REST Client 提供了两种方式的 Client:Java Low Level Cli ...

  3. spring boot集成Elasticsearch客户端

    spring boot整合Elasticsearch客户端 在spring boot程序应用中集成Elasticsearch客户端,并通过配置对连接进行管理. Elasticsearch的客户端Jav ...

  4. Spring Boot 集成 ElasticSearch,实现高性能搜索

    1.ElasticSearch介绍 Elasticsearch 是java开发的,基于 Lucene 的搜索引擎.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful Web接口.Elast ...

  5. spring boot集成Elasticsearch-SpringBoot(25)

    1. Elasticsearch-搜索应用服务器   1.1 什么是搜索引擎   搜索引擎(search engine )通常意义上是指:根据特定策略,运用特定的爬虫程序从互联网上搜集信息,然后对信息 ...

  6. ElasticSearch——Spring Boot 集成 ES 操作详解

    文章目录 ElasticSearch--Spring Boot 集成 ES 操作详解 1.SpringBoot 集成 ES 2.索引的API操作详解 3.文档的API操作详解 ElasticSearc ...

  7. 【Java进阶】Spring Boot集成ES

    目录 spring boot集成ES ElasticSearchConfig 测试文档的基本操作 Elasticsearch Clients 文档 spring boot集成ES Java REST ...

  8. Kafka 入门和 Spring Boot 集成

    2019独角兽企业重金招聘Python工程师标准>>> Kafka 入门和 Spring Boot 集成 概述 kafka 是一个高性能的消息队列,也是一个分布式流处理平台(这里的流 ...

  9. Elasticsearch实战篇——Spring Boot整合ElasticSearch

    2019独角兽企业重金招聘Python工程师标准>>> 当前Spring Boot很是流行,包括我自己,也是在用Spring Boot集成其他框架进行项目开发,所以这一节,我们一起来 ...

最新文章

  1. Web API 接口-JavaScript全部api接口文档
  2. bzoj 3339 莫队
  3. Struts2后期(这框架目前正处于淘汰状态)
  4. MPU6050开发 -- 初识
  5. python多级菜单查询简化版
  6. java中没有scanner_如何使用java.util.Scanner验证输入?
  7. LeetCode 797. 所有可能的路径(DFS)
  8. jdk1.8新特性的应用-Stream Api
  9. 2021年商业的几点变化
  10. mybatis 高级映射 - 一对多查询 - collection
  11. 计算机五个盘,电脑分盘分几个盘合适,您知道吗?
  12. 荣耀盒子无线网连接不上电脑连接服务器,华为荣耀盒子无法连接有线网络怎么解决...
  13. python怎么下载安装教程_python怎么下载?《python软件下载安装教程》
  14. 哪款 Linux 才是更好的 CentOS 替代品?
  15. 苹果再次要求供应商降价,将伤及自身
  16. 美国队长的工资 python代码-Python | 用Python画个美队盾牌送给你
  17. js 手机号码和电话号码(座机号)正则校验
  18. Oracle AWR 阙值影响历史执行计划
  19. iphone5s怎么取消iphone系统更新如何关闭系统更新提醒
  20. HZ服务器装系统速度变慢,360Hz刷新率有些什么厉害的地方?响应时间系统延迟测试...

热门文章

  1. Git生成ssh ksy后进行项目管理
  2. (6.1)各种USB接口简介
  3. 数学建模算法与应用:综合评价与决策方法(1)理想解法
  4. ML-Agents案例之双人足球
  5. 使用EF配合Linq语句进行查询
  6. docker部署codereview/gerrit
  7. 手机安全领域的领航者
  8. 三菱PLC第一篇:GXWORK3与三菱FX5UPLC同通过交换机连接
  9. 论文阅读笔记:vTPM
  10. Mac下CoreShell文件上传和下载配置