springboot 单测加入参数_Spring Boot集成Elasticsearch实战分享

171c161f2144fb20830ea24114afdaec.png

作者|java梦想口服液|简书

最近有读者问我能不能写下如何使用 Spring Boot 开发 Elasticsearch(以下简称 ES) 相关应用,今天就讲解下如何使用 Spring Boot 结合 ES。

可以在 ES 官方文档中发现,ES 为 Java REST Client 提供了两种方式的 Client: Java Low Level Client 和 Java High Level REST Client 。

低级别客户端,它允许通过 HTTP 请求与 ES 集群进行通信,API 本身不负责数据的编码解码,由用户去编码解码,它与所有的 ES 版本兼容。

高级客户端基于低级客户端,是从 6.0 才开始加入的,主要目标是为了暴露各 API 特定的方法,高版本客户端依赖于 ES 核心项目,将 Request 对象作为参数,返回一个 Response 对象,所有 API 都可以同步或异步调用。

本文就通过 Spring Boot 结合 Java High Level REST Client 来进行一些演示。

Spring Boot 集成 ES

Spring Boot 集成 ES 主要分为以下三步:

  1. 加入 ES 依赖
  2. 配置 ES
  3. 演示 ES 基本操作

加入依赖

首先创建一个项目,在项目中加入 ES 相关依赖,具体依赖如下所示:

org.elasticsearch    elasticsearch    7.1.0org.elasticsearch.client    elasticsearch-rest-high-level-client    7.1.0

创建 ES 配置

在配置文件 application.properties 中配置 ES 的相关参数,具体内容如下:

elasticsearch.host=localhostelasticsearch.port=9200elasticsearch.connTimeout=3000elasticsearch.socketTimeout=5000elasticsearch.connectionRequestTimeout=500

其中指定了 ES 的 host 和端口以及超时时间的设置,另外我们的 ES 没有添加任何的安全认证,因此 username 和 password 就没有设置。

然后在 config 包下创建 ElasticsearchConfiguration 类,会从配置文件中读取到对应的参数,接着申明一个 initRestClient 方法,返回的是一个 RestHighLevelClient ,同时为它添加 @Bean(destroyMethod = "close") 注解,当 destroy 的时候做一个关闭,这个方法主要是如何初始化并创建一个 RestHighLevelClient 。

@Configurationpublic class ElasticsearchConfiguration {    @Value("${elasticsearch.host}")    private String host;    @Value("${elasticsearch.port}")    private int port;    @Value("${elasticsearch.connTimeout}")    private int connTimeout;    @Value("${elasticsearch.socketTimeout}")    private int socketTimeout;    @Value("${elasticsearch.connectionRequestTimeout}")    private int connectionRequestTimeout;    @Bean(destroyMethod = "close", name = "client")    public RestHighLevelClient initRestClient() {        RestClientBuilder builder = RestClient.builder(new HttpHost(host, port))                .setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder                        .setConnectTimeout(connTimeout)                        .setSocketTimeout(socketTimeout)                        .setConnectionRequestTimeout(connectionRequestTimeout));        return new RestHighLevelClient(builder);    }}

定义文档实体类

首先在 constant 包下定义常量接口,在接口中定义索引的名字为 user :

public interface Constant {    String INDEX = "user";}
然后在 `document` 包下创建一个文档实体类:public class UserDocument { private String id; private String name; private String sex; private Integer age; private String city; // 省略 getter/setter}

ES 基本操作

在这里主要介绍 ES 的索引、文档、搜索相关的简单操作,在 service 包下创建 UserService类。

索引操作

在这里演示创建索引和删除索引:

创建索引

在创建索引的时候可以在 CreateIndexRequest 中设置索引名称、分片数、副本数以及 mappings,在这里索引名称为 user ,分片数 number_of_shards 为 1,副本数 number_of_replicas 为 0,具体代码如下所示:

public boolean createUserIndex(String index) throws IOException {    CreateIndexRequest createIndexRequest = new CreateIndexRequest(index);    createIndexRequest.settings(Settings.builder()            .put("index.number_of_shards", 1)            .put("index.number_of_replicas", 0)    );    createIndexRequest.mapping("{" +            "  "properties": {" +            "    "city": {" +            "      "type": "keyword"" +            "    }," +            "    "sex": {" +            "      "type": "keyword"" +            "    }," +            "    "name": {" +            "      "type": "keyword"" +            "    }," +            "    "id": {" +            "      "type": "keyword"" +            "    }," +            "    "age": {" +            "      "type": "integer"" +            "    }" +            "  }" +            "}", XContentType.JSON);    CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);    return createIndexResponse.isAcknowledged();}

通过调用该方法,就可以创建一个索引 user ,索引信息如下:

88dd09cf9f7bf709aca04f730f95efcc.png

关于 ES 的 Mapping 可以看下这篇文章: 一文搞懂 Elasticsearch 之 Mapping

删除索引

在 DeleteIndexRequest 中传入索引名称就可以删除索引,具体代码如下所示:

public Boolean deleteUserIndex(String index) throws IOException {    DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index);    AcknowledgedResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);    return deleteIndexResponse.isAcknowledged();}

介绍完索引的基本操作,下面介绍文档的相关操作:

文档操作

在这里演示下创建文档、批量创建文档、查看文档、更新文档以及删除文档:

创建文档

创建文档的时候需要在 IndexRequest 中指定索引名称, id 如果不传的话会由 ES 自动生成,然后传入 source,具体代码如下:

public Boolean createUserDocument(UserDocument document) throws Exception {    UUID uuid = UUID.randomUUID();    document.setId(uuid.toString());    IndexRequest indexRequest = new IndexRequest(Constant.INDEX)            .id(document.getId())            .source(JSON.toJSONString(document), XContentType.JSON);    IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);    return indexResponse.status().equals(RestStatus.OK);}

下面通过调用这个方法,创建两个文档,具体内容如下:

f0551c0a740ffb8289867c3807b21baa.png

批量创建文档

在一个 REST 请求中,重新建立网络开销是十分损耗性能的,因此 ES 提供 Bulk API, 支持在一次 API 调用中,对不同的索引进行操作 ,从而减少网络传输开销,提升写入速率。

下面方法是批量创建文档,一个 BulkRequest 里可以添加多个 Request,具体代码如下:

public Boolean bulkCreateUserDocument(List documents) throws IOException {    BulkRequest bulkRequest = new BulkRequest();    for (UserDocument document : documents) {        String id = UUID.randomUUID().toString();        document.setId(id);        IndexRequest indexRequest = new IndexRequest(Constant.INDEX)                .id(id)                .source(JSON.toJSONString(document), XContentType.JSON);        bulkRequest.add(indexRequest);    }    BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);    return bulkResponse.status().equals(RestStatus.OK);}

下面通过该方法创建些文档,便于下面的搜索演示。

查看文档

查看文档需要在 GetRequest 中传入索引名称和文档 id,具体代码如下所示:

public UserDocument getUserDocument(String id) throws IOException {    GetRequest getRequest = new GetRequest(Constant.INDEX, id);    GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);    UserDocument result = new UserDocument();    if (getResponse.isExists()) {        String sourceAsString = getResponse.getSourceAsString();        result = JSON.parseObject(sourceAsString, UserDocument.class);    } else {        logger.error("没有找到该 id 的文档");    }    return result;}

下面传入文档 id 调用该方法,结果如下所示:

05e18e314ca110b5aa1ce268560853ae.png

更新文档

更新文档则是先给 UpdateRequest 传入索引名称和文档 id,然后通过传入新的 doc 来进行更新,具体代码如下:

public Boolean updateUserDocument(UserDocument document) throws Exception {    UserDocument resultDocument = getUserDocument(document.getId());    UpdateRequest updateRequest = new UpdateRequest(Constant.INDEX, resultDocument.getId());    updateRequest.doc(JSON.toJSONString(document), XContentType.JSON);    UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);    return updateResponse.status().equals(RestStatus.OK);}

下面将文档 id 为 9b8d9897-3352-4ef3-9636-afc6fce43b20 的文档的城市信息改为 handan ,调用方法结果如下:

2f58f2326a94af6d9ddc659a4970d2ad.png

删除文档

删除文档只需要在 DeleteRequest 中传入索引名称和文档 id,然后执行 delete 方法就可以完成文档的删除,具体代码如下:

public String deleteUserDocument(String id) throws Exception {    DeleteRequest deleteRequest = new DeleteRequest(Constant.INDEX, id);    DeleteResponse response = client.delete(deleteRequest, RequestOptions.DEFAULT);    return response.getResult().name();}

介绍完文档的基本操作,接下来对搜索进行简单介绍:

搜索操作

对 ES 的 DSL 语法还不是很熟悉的可以先看下这篇文章: 看完这篇还不会 Elasticsearch 搜索,那我就哭了!

简单的搜索操作需要在 SearchRequest 中设置将要搜索的索引名称(可以设置多个索引名称),然后通过 SearchSourceBuilder 构造搜索源,下面将 TermQueryBuilder 搜索查询传给 searchSourceBuilder ,最后将 searchRequest 的搜索源设置为 searchSourceBuilder ,执行 search 方法实现通过城市进行搜索,具体代码如下所示:

public List searchUserByCity(String city) throws Exception {    SearchRequest searchRequest = new SearchRequest();    searchRequest.indices(Constant.INDEX);    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("city", city);    searchSourceBuilder.query(termQueryBuilder);    searchRequest.source(searchSourceBuilder);    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);    return getSearchResult(searchResponse);}

该方法的执行结果如图所示:

586d62c100a8ba2680c4635ede81e18d.png

聚合搜索

ES 聚合搜索相关知识可以看下这篇文章: Elasticsearch 之聚合分析入门

聚合搜索就是给 searchSourceBuilder 添加聚合搜索,下面方法是通过 TermsAggregationBuilder 构造一个先通过城市就行分类聚合,其中还包括一个子聚合,是对年龄求平均值,然后在获取聚合结果的时候,可以使用通过在构建聚合时的聚合名称获取到聚合结果,具体代码如下所示:

public List aggregationsSearchUser() throws Exception {    SearchRequest searchRequest = new SearchRequest(Constant.INDEX);    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();    TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_city")            .field("city")            .subAggregation(AggregationBuilders                    .avg("average_age")                    .field("age"));    searchSourceBuilder.aggregation(aggregation);    searchRequest.source(searchSourceBuilder);    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);    Aggregations aggregations = searchResponse.getAggregations();    Terms byCityAggregation = aggregations.get("by_city");    List userCityList = new ArrayList<>();    for (Terms.Bucket buck : byCityAggregation.getBuckets()) {        UserCityDTO userCityDTO = new UserCityDTO();        userCityDTO.setCity(buck.getKeyAsString());        userCityDTO.setCount(buck.getDocCount());        // 获取子聚合        Avg averageBalance = buck.getAggregations().get("average_age");        userCityDTO.setAvgAge(averageBalance.getValue());        userCityList.add(userCityDTO);    }    return userCityList;}

下面是执行该方法的结果:

5cb1dbf104cee199f70187ac889d49df.png

到此为止,ES 的基本操作就简单介绍完了,大家可以多动手试试,不会的可以看下官方文档。

总结

本文的完整代码在 https://github.com/wupeixuan/SpringBoot-Learn 的 elasticsearch 目录下。

Spring Boot 结合 ES 还是比较简单的,大家可以下载项目源码,自己在本地运行调试这个项目,更好地理解如何在 Spring Boot 中构建基于 ES 的应用。

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

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

相关文章

计算机主机安装系统安装系统安装软件,电脑安装软件时提示安装过程出错系统设置未被修改怎么办...

‍电脑安装软件&#xff0c;尤其是安全管理这一类软件&#xff0c;可能会出现安装失败的情况&#xff0c;提示安装过程出现错误&#xff0c;未修改系统设置等。这是怎么回事?这些软件在安装的时候可能会修改系统相关的核心设置&#xff0c;所以电脑系统会阻止其安装。下面让我…

python一个函数调用另一个函数_在Python中将函数作为另一个函数的参数传入并调用的方法...

在Python中&#xff0c;函数本身也是对象&#xff0c;所以可以将函数作为参数传入另一函数并进行调用 在旧版本中&#xff0c;可以使用apply(function, *args, **kwargs)进行调用&#xff0c;但是在新版本中已经移除&#xff0c;以function(*args, **kwargs)进行替代&#xff0…

ps图片拖不进去_PS教学:你的logo还不够高大上?7步教做出黄色金属质感logo

今天美迪君向大家分享一下&#xff0c;如何用ps简单制作带有黄色金属质感的logo方法&#xff0c;难度不仅不大&#xff0c;且制造出来的logo也是非常漂亮&#xff0c;值得大家学习。接下来就为大家演示一下制造的方法。1、打开PS&#xff0c;CtrlN新建一个1920*1080的画布(根据…

简单比对照片是否相同_小新说法 | 如何认定商标是否侵权?

如何认定商标是否侵权&#xff1f;原创 | 高姗 江苏东能律师事务所商标是商品的生产者、经营者在其生产、制造、加工、拣选或者经销的商品上或者服务的提供者在其提供的服务上采用的&#xff0c;用于区别商品或服务来源的&#xff0c;包括文字、图形、字母、数字、三维标志、颜…

验证码编写_编写干净的测试–验证或不验证

验证码编写在编写使用模拟对象的单元测试时&#xff0c;请遵循以下步骤&#xff1a; 配置我们的模拟对象的行为。 调用测试的方法。 验证是否已调用模拟对象的正确方法。 第三步的描述实际上有点误导&#xff0c;因为通常我们最终会验证是否调用了正确的方法以及未调用模拟…

单片机拼字程序怎么做_家装行业做小程序怎么样?

对于家装行业&#xff0c;给大家提到了很多获客引流的方式&#xff0c;无论是线上还是线下&#xff0c;只要坚持去做&#xff0c;最后肯定会取得成果的。关于线下的给大家提到最多的就是合作共赢的模式来拓客&#xff0c;线上主要就是打电话和表单或者进入平台的形式&#xff0…

计算机三级考试网络技术怎么复习,考前数天如何突破性通过计算机等级考试之三级网络技术篇...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼计算机等级考试只有几天的时间了&#xff0c;复习已久的你现在该做些什么?最新出版的书&#xff0c;结合近年等考真题&#xff0c;考三级网络技术的同学需要的可以看看&#xff0c;我找来了目录和内容简介&#xff0c;不错的一本书…

python 删除csv第一行_python 标准库学习之 csv

本文由作者 凭海临风 授权刊登。原文地址&#xff1a;https://jeffsui.github.io/2020/01/02/python-standard-library-csv/文档路径官方文档&#xff1a;https://docs.python.org/zh-cn/3.8/library/csv.htmlCSV 文件格式文件扩展名为.csv&#xff0c;通用的电子表格文件格式&…

Java 8之前和之后的Lambda表达式

Java 8之前和之后的几个示例程序的快速指南。Java8 Concepts进一步简化了代码&#xff0c;并且对核心逻辑&#xff08;而不是语法&#xff09;产生了深远影响。 1.简介 在本教程中&#xff0c;我们将学习如何使用Java 8编写程序 lambda和Stream概念以及示例。 许多开发人员认…

idea java主题_IDEA变身超级形态,需要这个酷炫主题

码个蛋(codeegg) 第 1090 次推文作者&#xff1a;CodeWhite7链接&#xff1a;https://blog.csdn.net/weixin_46146269/article/details/104793277前言IDEA&#xff0c;全称 IntelliJ IDEA &#xff0c;是 Java 语言的集成开发环境&#xff0c; IDEA 在业界被公认为是最好的 jav…

儿童python编程能给孩子带来哪些好处_python编程入门学习对孩子成长有哪些优势?...

python编程语言学习有意义吗&#xff1f; python编程语言是少儿编程培训课程中重要的组成部分&#xff0c;随着越来越多的孩子开始接触和学习编程&#xff0c;通过编程学习培养孩子良好的学习习惯和锻炼提升孩子逻辑思维能力。在python编程培训班学习过程中&#xff0c;通过pyt…

yii2 html ul,yii2导航小部件子菜单类

我使用adminLTE主题进行bootstrap,它使用treeview-menu类来操作子菜单.Nav::widget([options > [class > sidebar-menu treeview],items > [[label > Menu 1, url > [/a/index]],[label > Menu 2, url > [/custom-perks/index]],[label > Submenu, ite…

百度云盘照片导入华为相册里_必须知道的相册管理工具

相信很多人都会在手机上存许多值得回忆的照片&#xff0c;为了避免丢失&#xff0c;我们常常会使用网盘工具来管理我们的照片&#xff0c;例如&#xff0c;比较常用的有百度网盘、天翼云盘、115网盘这三款工具&#xff0c;那么这三款网盘在相册功能上有什么特色呢&#xff1f;今…

微信H5 回调_PHP实现微信H5支付

今头日条一小马奔腾 2019-09-27 18:44:37开发前配置进行代码接入前&#xff0c;需在微信后台填写授权回调域名&#xff0c;此域名必须经过ICP备案开发主要流程用户下单时选择微信支付商户进行业务逻辑处理并调用微信统一下单接口&#xff0c;微信H5交易类型为&#xff1a;trade…

freemarker html 乱码,Freemarker生成静态html文件及中文乱码的问题.pdf

Freemarker生成静态html文件及中文乱码的问题,freemarker静态化页面,freemarker静态化,freemarker乱码,freemarker静态方法,freemarker中文乱码,freemarker网页静态化,freemarker生成word,freemarker代码生成器,freemarker生成htmlFreeMarker 允许 Java servlet 保持图形设计同…

java 泛型嵌套泛型_Java泛型简介–第6部分

java 泛型嵌套泛型这是关于泛型的介绍性讨论的延续&#xff0c; 此处的先前部分可以在此处找到。 在上一篇文章中&#xff0c;我们讨论了关于类型参数的递归边界。 我们看到了递归绑定如何帮助我们重用了车辆比较逻辑。 在该文章的结尾&#xff0c;我建议当我们不够谨慎时&…

优化自定义函数_Pandas常见的性能优化方法

文章来源于Datawhale &#xff0c;作者阿水Pandas是数据科学和数据竞赛中常见的库&#xff0c;我们使用Pandas可以进行快速读取数据、分析数据、构造特征。但Pandas在使用上有一些技巧和需要注意的地方&#xff0c;如果你没有合适的使用&#xff0c;那么Pandas可能运行速度非常…

pycharm cant open file_PyCharm

1.创建项目PyCharm是一种Python IDE.PyCharm的功能到底有多强大&#xff0c;我也说不清楚&#xff0c;今天只是介绍一下关于Pycharm创建项目的问题.✦ PyCharm可以将一个文件夹作为工程(或项目)进行打开.如图1所示&#xff0c;先创建两个文件夹(pyc1和pyc2)&#xff0c;在文件夹…

adminlte支持html5吗,spring boot:用adminlte做前端

标签(空格分隔)&#xff1a; sringboot adminlte thymeleafspring boot 和 adminlte没有紧密的联系&#xff0c;只是最近在做的一个东西用spring boot做后端用adminlte做前端&#xff0c;所以就放到spring boot系列里面讲。架构原理adminlte只是一个库&#xff0c;说不上什么框…

如何通过示例使用Java中的Exchanger

大家好&#xff0c;如果您在并发Java应用程序中工作&#xff0c;那么您可能听说过java.util.concurrent包的Exchanger类。 Java中的Exchanger是Java 1.5中与CountDownLatch &#xff0c; CyclicBarrier和Semaphores一起引入的另一个并发或同步实用程序。 顾名思义&#xff0c; …