【SpringBoot】整合Elasticsearch 快速入门操作索引

news2024/11/21 0:35:35

官网操作文档:Elasticsearch Clients | Elastic      

         踩坑太多了。。。这里表明一下Spring Boot2.4以上版本可能会出现问题,所以我降到了2.2.1.RELEASE。对于现在2023年6月而言,Es版本已经到了8.8,而SpringBoot版本已经到了3.x版本。如果是高版本的Boot在配置类的时候会发现RestHighLevelClient已过时。从官网也可以看的出来RestHighLevelClient已过时。所以这篇博文中不会用到关于RestHighLevelClient的Api。

        此篇博文的对应版本关系:Elasticsearch 8.2.0 + Spring Boot 2.7.5。在进入到下面的案例,我需要在这之前先介绍RestClient、RestHighLevelClient、RestClientTransport、ElasticsearchClient。

RestClient

        这个类主要是用作于与服务端IP以及端口的配置,在其的builder()方法可以设置登陆权限的账号密码、连接时长等等。总而言之就是服务端配置

RestClientTransport

        这是Jackson映射器创建传输。建立客户端与服务端之间的连接传输数据。这是在创建ElasticsearchClient需要的参数,而创建RestClientTransport就需要上面创建的RestClient。

ElasticsearchClient

        这个就是Elasticsearch的客户端。调用Elasticsearch语法所用到的类,其就需要传入上面介绍的RestClientTransport。

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- 高版本还需引入此依赖 -->
<dependency>
    <groupId>jakarta.json</groupId>
    <artifactId>jakarta.json-api</artifactId>
    <version>2.0.0</version>
</dependency>

修改yml

        需要注意的是账号和密码可以不需要,看自己的Elasticsearch是否有配置账号密码。具体对Elasticsearch的登陆操作可以看:中偏下的位置就是对账号密码的设置。【Linux】Docker部署镜像环境 (持续更新ing)_小白的救赎的博客-CSDN博客

server:
  port: 8080

elasticsearch:
  hostAndPort: 192.168.217.128:9200 # 低版本使用的
  ip: 192.168.217.128
  port: 9200
  username: elastic
  password: 123456
  connectionTimeout: 1000
  socketTimeout: 30000

配置类    

        这里演示两种情况的配置:第一个代码块是SpringBoot2.4以下 + 7.x版本Elasticsearch的配置。第二个代码块是Spring2.4以上 + 8.x版本Elasticsearch的配置。

@Configuration
public class ElasticConfig extends AbstractElasticsearchConfiguration {

    @Value("${elasticsearch.hostAndPort}")
    private String hostAndPort;

    @Value("${elasticsearch.username}")
    private String username;

    @Value("${elasticsearch.password}")
    private String password;

    @Value("${elasticsearch.connectionTimeout}")
    private String connectTimeout;

    @Value("${elasticsearch.socketTimeout}")
    private String socketTimeout;

    /**
     * create Elasticsearch client
     * @return RestHighLevelClient
     */
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username, password));
        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(hostAndPort)
                .withConnectTimeout(Long.parseLong(connectTimeout))
                .withSocketTimeout(Long.parseLong(socketTimeout))
                .withBasicAuth(username, password)
                .build();
        return RestClients.create(clientConfiguration).rest();
    }

    /**
     * 将连接传入 Elasticsearch在 Spring Boot的模板类中
     * @return 返回 Es的模板类
     */
    @Bean
    public ElasticsearchRestTemplate elasticsearchRestTemplate() {
        return new ElasticsearchRestTemplate(elasticsearchClient());
    }
}
@Configuration
public class ElasticConfig {

    @Value("${elasticsearch.ip}")
    private String ip;

    @Value("${elasticsearch.port}")
    private String port;

    @Value("${elasticsearch.username}")
    private String username;

    @Value("${elasticsearch.password}")
    private String password;

    @Value("${elasticsearch.connectionTimeout}")
    private String connectTimeout;

    @Value("${elasticsearch.socketTimeout}")
    private String socketTimeout;

    /**
     * create Elasticsearch client
     * @return RestHighLevelClient
     */
    @Bean
    public ElasticsearchClient elasticsearchClient() {
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username, password));

        RestClient restClient = RestClient.builder(
                new HttpHost(ip, Integer.parseInt(port)))
                .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))
                .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
                    @Override
                    public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) {
                        return builder.setConnectTimeout(Integer.parseInt(connectTimeout)).setSocketTimeout(Integer.parseInt(socketTimeout));
                    }
                }).build();

        ElasticsearchTransport transport 
                        = new RestClientTransport(restClient, new JacksonJsonpMapper());

        return new ElasticsearchClient(transport);
    }
}

控制层

        这里为了方便快速入门,就把所有业务代码都放在控制层中了。这篇博文主要是对索引进行操作,所以说获取到ElasticsearchClient后会调用indices()方法,这个方法就是操作索引的方法。次代码块是展示变量以及类注解。后面逐一暂时各个测试代码块Api以及返回结果。

@RestController
@RequestMapping("/es")
@Slf4j
public class EsController{

    @Autowired
    private ElasticConfig elasticConfig;
}

创建索引

/**
 * create index
 * @return is success?
 */
@PutMapping("/createIndex")
public boolean createIndex() throws IOException {
    CreateIndexRequest indexRequest 
                        = new CreateIndexRequest.Builder().index("user").build();
    CreateIndexResponse indexResponse 
                        = elasticConfig.esClient().indices().create(indexRequest);

    boolean isSuccess = indexResponse.acknowledged();
    if(isSuccess) {
        log.info("创建索引成功");
    } else {
        log.info("创建索引失败");
    }
    return isSuccess;
}

查询单个索引数据

/**
 * get one index data by id
 */
@GetMapping("/getIndex")
public void getIndex() throws IOException {
   GetResponse<User> response = elasticConfig.esClient().get(g -> g
           .index("user")
           .id("1000")
           ,User.class
   );
   if(response.found()) {
       log.info("此用户的姓名为,{}",response.source().getUsername());
   } else {
       log.info("未查询到此用户");
   }
}

删除索引

        这里我测试删除索引成功后又把索引添加了回去。为了后面的其它操作做准备。

/**
 * delete one index
 */
@DeleteMapping("/deleteIndex")
public boolean deleteIndex() throws IOException {
    DeleteIndexRequest indexRequest 
                        = new DeleteIndexRequest.Builder().index("user").build();
    DeleteIndexResponse deleteResponse 
                        = elasticConfig.esClient().indices().delete(indexRequest);
    boolean isSuccess = deleteResponse.acknowledged();
    if(isSuccess) {
        log.info("删除索引成功");
    } else {
        log.info("删除索引失败");
    }
    return isSuccess;
}

增加索引内容

        这里我新增了个实体类,方便添加到索引内容中。这里大概有四种方式可以创建,这里我演示了三种方式,第四种是使用到了ElasticsearchAsyncClient ,这是Elastic异步客户端。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String username;
    private String sex;
    private Integer age;
}
/**
 * 向索引内容插入数据
 */
@PostMapping("/insertIndexData")
public void insertIndexData() throws IOException {
    User user = new User("zhangSan","男",18);
    /*
    第一种方式:使用DSL语法创建对象
    IndexRequest<User> indexRequest = IndexRequest.of(i -> i
            .index("user")
            .id("1000")
            .document(user)
    IndexResponse indexResponse = elasticConfig.esClient().index(indexRequest.build());
    );
     */
    /*
    第二种方式:使用Elasticsearch客户端上配置的对象映射器映射到JSON。
    IndexResponse indexResponse = elasticConfig.esClient().index(i -> i
            .index("user")
            .id("1000")
            .document(user)
    );
     */
    // 第三种方式:使用构造器模式
    IndexRequest.Builder<User> indexRequest = new IndexRequest.Builder<>();
    indexRequest.index("user");
    indexRequest.id("1000");
    indexRequest.document(user);
    IndexResponse indexResponse = elasticConfig.esClient().index(indexRequest.build());
    log.info("index,{}",indexResponse.index());
    log.info("id,{}",indexResponse.id());
    log.info("version,{}",indexResponse.version());
}

批量添加索引数据

        BulkRequest包含一组操作,每个操作都是具有多个变体的类型。为了创建这个请求,可以方便地将构建器对象用于主请求,并将流利的DSL用于每个操作。下面的示例显示了如何为列表或应用程序对象编制索引。

        operations是BulkOperation的生成器,BulkOperation是一种变体类型。此类型具有索引创建更新删除变体。

/**
 * 批量插入索引数据
 */
@PostMapping("/batchInsertIndex")
public void batchInsertIndex() throws IOException {
    // 将需要批量添加的数据放到List中
    List<User> list = new ArrayList<>();
    list.add(new User("liSi","女",20));
    list.add(new User("wangWu","男",22));
    // 使用BulkRequest的构造器
    BulkRequest.Builder request = new BulkRequest.Builder();
    for(User user : list) {
        request.operations(l -> l
                .index(i -> i
                        .index("user")
                        .document(user)
                )
        );
    }
    BulkResponse response = elasticConfig.esClient().bulk(request.build());
    if(response.errors()) {
        log.info("批量插入报错");
    } else {
        log.info("批量插入成功");
    }
}

批量删除索引数据

/**
 * 批量删除索引数据
 */
@DeleteMapping("/batchDeleteIndex")
public void batchDeleteIndex() throws IOException {
    BulkRequest.Builder request = new BulkRequest.Builder();
    // 根据id做到删除索引的数据
    request.operations(l -> l
            .delete(i -> i
                    .index("user")
                    .id("vGK5sogBM87kk5Mw8V0P")
            )
    );
    request.operations(l -> l
            .delete(i -> i
                    .index("user")
                    .id("u2K5sogBM87kk5Mw8V0P")
            )
    );
    BulkResponse response = elasticConfig.esClient().bulk(request.build());
    if(response.errors()) {
        log.info("批量删除报错");
    } else {
        log.info("批量删除成功");
    }
}

          这里批量删除接口测试完后,我又批量添加了几行数据,方便下面方法的测试。

// 以下就是我添加的数据
list.add(new User("liSi","女",20));
list.add(new User("wangWu","男",22));
list.add(new User("zhaoLiu","男",20));
list.add(new User("xiaoQi","女",21));

简单查询/单条件

        可以组合多种类型的搜索查询。我们将从简单的文本匹配查询开始。单条件准确查询主要用到的关键字是term。而模糊查询就需要用到match。而match这里就不演示了。

/**
 * 单条件查询
 */
@GetMapping("/search")
public void search() throws IOException {
    SearchResponse<User> response = elasticConfig.esClient().search(s -> s
            .index("user")
            .query(q -> q
                    .term(e -> e
                            .field("age")
                            .value("20")
                    )
            ), User.class
    );
    // 获取查询后的命中条数:其中包括 TotalHitsRelation 以及 total
    TotalHits total = response.hits().total();
    boolean isExactResult = total.relation() == TotalHitsRelation.Eq;
    if (isExactResult) {
        log.info("There are " + total.value() + " results");
    } else {
        log.info("There are more than " + total.value() + " results");
    }
    // 解析查询到的所有信息
    List<Hit<User>> hits = response.hits().hits();
    for(Hit<User> hit : hits) {
        log.info("id,{}", hit.id());
    }
}

多条件查询 / 范围查询

        Elasticsearch允许将单个查询组合起来,以构建更复杂的搜索请求。当前数据有五条,为了更好的多条件查询,我又增加了5条数据。多条件查询用到的关键字主要就是bool

// 起初的5条数据
list.add(new User("zhangSan","男",18));
list.add(new User("liSi","女",20));
list.add(new User("wangWu","男",22));
list.add(new User("zhaoLiu","男",20));
list.add(new User("xiaoQi","女",21));
// 以下就是我添加的数据
list.add(new User("zhangSan","男",20));
list.add(new User("zhangSan","男",21));
list.add(new User("zhangSan","男",22));
list.add(new User("zhangSan","男",23));
list.add(new User("zhangSan","男",24));
/**
 * 多条件查询
 */
@GetMapping("/batchSearch")
public void batchSearch() throws IOException {
    // 查询性别
    Query sex = MatchQuery.of(m -> m
            .field("sex")
            .query("男")
    )._toQuery();
    // 查询年龄区间
    Query age = RangeQuery.of(r -> r
            .field("age")
            .lte(JsonData.of(20))
            .gte(JsonData.of(18))
    )._toQuery();
    // 结合性别和年龄区间查询来搜索用户索引
    SearchResponse<User> response = elasticConfig.esClient().search(s -> s
            .index("user")
            .query(q -> q
                .bool(b -> b
                    .must(sex)
                    .must(age)
                )
            ),User.class
    );
    // 获取查询后的命中条数:其中包括 TotalHitsRelation 以及 total
    TotalHits total = response.hits().total();
    boolean isExactResult = total.relation() == TotalHitsRelation.Eq;
    if (isExactResult) {
        log.info("There are " + total.value() + " results");
    } else {
        log.info("There are more than " + total.value() + " results");
    }
    // 解析查询到的所有信息
    List<Hit<User>> hits = response.hits().hits();
    for(Hit<User> hit : hits) {
        log.info("id,{}", hit.id());
    }
}

分页查询

        主要就是Elasticsearch语法中的from与size表示:当前页的开始索引处以及每页条数。

/**
 * 分页查询
 */
@GetMapping("/searchByPage")
public void searchByPage() throws IOException {
    // 假设每页3条数据 那么查询第二页的参数就是:开始索引处为(2 - 1) * 3 = 3 以及 每页条数3
    SearchResponse<User> response = elasticConfig.esClient().search(b -> b
            .index("user")
            .from(3)
            .size(3)
            ,User.class
    );
    log.info("查询到的总条数为,{}",response.hits().total().value());
    List<Hit<User>> hits = response.hits().hits();
    for(Hit<User> hit : hits) {
        log.info("查询到的id,{}", hit.id());
    }
}

查询所有索引数据

/**
 * get all index data
 */
@GetMapping("/getAllIndex")
public void getAllIndex() throws IOException {
    SearchResponse<User> response = elasticConfig.esClient().search(s -> s
            .index("user")
            ,User.class);
    // 解析查询到的所有信息
    List<Hit<User>> hits = response.hits().hits();
    for(Hit<User> hit : hits) {
        log.info(String.valueOf(hit.source()));
    }
}

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

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

相关文章

【实战】Python爬虫之代理使用详解

在Python爬虫中&#xff0c;代理的使用非常常见。代理的主要作用是隐藏客户端的真实IP地址&#xff0c;从而实现更高的网络访问速度和更好的访问隐私保护。下面我们将通过Python爬虫的实例&#xff0c;带你详细了解Python爬虫中代理的使用方法。 目录 ## 1. 代理原理和作用 …

多维度员工信息整合查询——红海云员工信息数字化管理实用指南(中)

红海云员工全生命周期数字化管理平台从信息源头开始管控员工数据质量&#xff0c;在员工数据的采集、更新、审核环节采用多种方式保障员工信息的准确性、完整性、时效性和一致性&#xff0c;为企业搭建坚实可靠的人力资源管理数字化基座。但在有了准确可靠的员工数据基础后&…

APP测试应该从哪些方面入手?其实就这几点

前言 还在苦恼怎么去测APP吗&#xff1f; 一定要记住这几个方向&#xff0c;然后流程化的去执行&#xff0c;一来严谨规范&#xff0c;二来不会有遗漏。 1、需求检查&#xff1a; 在需求评审的时候展现你的业务能力啦&#xff01;不过还是得口下留情哟。&#xff08;PM心里瑟…

GitOps指南

GitOps基于CICD和IaC&#xff0c;以一致的方式管理代码和部署&#xff0c;是DevOps最佳实践之一。本文完整介绍了GitOps的理念和实践&#xff0c;并介绍了Weave Cloud的GitOps模型和工具&#xff0c;从整体上提供了实践GitOps的路径和方案。原文&#xff1a;Guide To GitOps[1]…

C++中的一些小技巧,numeric_limits、static_cast、reinterpret_cast方法内存验证

1、获取指定类型的最大值和最小值 在准备求一堆double数据中的最大值最小值的时候&#xff0c;常规做法是预估这堆数据的最大最小值&#xff0c;然后进行比较求&#xff0c;在重构别人代码的时候发现&#xff0c;可以准确知道double类型最大值或者最小值&#xff0c;获取方法如…

Apikit 自学日记:分享 API 文档

开启/关闭在线分享 您可以在线分享项目给团队以外的人&#xff0c;其他人可以通过分享链接在线查看API文档并且进行API测试。通过这种方式查看API文档不需要注册账号&#xff0c;用户可方便查看接口文档和测试接口。 在项目内&#xff0c;点击进入项目管理菜单&#xff0c;选择…

银河麒麟部署达梦8数据库开发者版本详细教程

我的系统信息如下&#xff1a; 系统架构&#xff1a;X86架构 系统信息&#xff1a;银河麒麟&#xff08;V10&#xff09; CPU&#xff1a;interl E5 官方安装文档&#xff1a;安装及卸载 | 达梦技术文档 (dameng.com) 数据库下载&#xff1a; 下载地址&#xff1a;产品下载…

【深度学习】2-5 神经网络-批处理

批处理&#xff08;Batch Processing&#xff09;是指在深度学习中每次迭代更新模型参数时同时处理多个样本的方式。 批处理时要注意对应维度的元素个数要一致 关于之前手写数字识别的例子&#xff1a; 用图表示&#xff0c;可以发现&#xff0c;多维数组的对应维度的元素个数…

体验DIY物联网浏览器(谷歌内核兼容性好支持H264视频播放)

一、功能及快捷键说明(说明32位兼容64位,版本往下看) 功能及快捷键图说明,不可多得的浏览器,支持右键自定义菜单... 二、下载安装包 2.1 版本 100.0.230 (支持H264版本)介绍 cefsharp物联网浏览器-支持H264(100.0.230)_cefsharp h264_久爱物联网的博客-CSDN博客 …

《论文阅读》用于情感分析的融合预训练表情符号特征增强

《论文阅读》用于情感分析的融合预训练表情符号特征增强 前言简介模型构架实验结果总结前言 你是否也对于理解论文存在困惑? 你是否也像我之前搜索论文解读,得到只是中文翻译的解读后感到失望? 小白如何从零读懂论文?和我一起来探索吧! 今天为大家带来的是《Fusion Pr…

SonarScanner扫描本地项目代码

一、Windows系统扫描 下载SonarScanner 去SonarQube官网下载相应系统的SonarScanner 点这里跳转 设置环境变量 下载好试个压缩文件&#xff0c;解压到你想存放的位置&#xff0c;设置环境变量 新增变量名&#xff1a;SONAR_SCANNER_HOME&#xff0c;值&#xff1a;你解压Sona…

ansible知识

在物理机查看环境&#xff0c;[kioskfoundation0 ~]$ cat /etc/rht 先清空当前环境&#xff0c;[kioskfoundation0 ~]$ rht-clearcourse 0 再切换rh294环境&#xff0c;[kioskfoundation0 ~]$ rht-setcourse rh294 验证环境是否切换成功&#xff0c;[kioskfoundation0 ~]$ cat…

2023年6月DAMA-CDGA/CDGP数据治理工程师认证找这家

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

清北「学渣」创业心路:AI 新时代已来,不参与对不起自己

内容一览&#xff1a;近日&#xff0c;HyperAI 超神经有幸接触到 SegmentFault AIGC Hackathon 2023 北京站二等奖获得者 OAISIS 团队&#xff0c;与他们畅聊了本次参赛的心路历程以及比赛之外团队的工作和生活。交谈中&#xff0c;三位年轻人显露出的自信、沉着、从容令人印象…

自动识别字幕

抖音官方出品的视频剪辑工具&#xff0c;国内版本和网易见外工作台一样&#xff0c;智能生成字幕功能只能识别中文和英文两种语言。 但是剪映国际版就支持英语、日语、韩语、葡萄牙语、俄语、印度尼西亚语、西班牙语还有德语总共八种语言。 剪映国际版字幕小助手 地址&#x…

【Android开发基础】传感器(方向传感器、加速度传感器)

文章目录 一、引言二、设计1、指南针&#xff08;方向传感器&#xff09;&#xff08;1&#xff09;效果&#xff08;2&#xff09;UI设计&#xff08;3&#xff09;功能设计 2、摇一摇&#xff08;加速度传感器&#xff09;&#xff08;1&#xff09;效果&#xff08;2&#x…

华硕天选2ubuntu18.04升级内核后黑屏

https://piaoyun.cc/post/26957.html 1.开机&#xff0c;进入grub画面 2.按’‘‘e’’’ 进入编辑开机指令的模式,同样找到’‘‘quite splash’’,并在后面加上对应的字。 1.Intel 82852/82855 或8系列显示晶片&#xff1a;i915.modeset1或i915.modeset0 2.Nvidia&#xff…

SpringBoot集成支付宝支付 - 少走弯路就看这篇

最近在做一个网站&#xff0c;后端采用了SpringBoot&#xff0c;需要集成支付宝进行线上支付&#xff0c;在这个过程中研究了大量支付宝的集成资料&#xff0c;也走了一些弯路&#xff0c;现在总结出来&#xff0c;相信你读完也能轻松集成支付宝支付。 在开始集成支付宝支付之前…

【神经网络】梯度检测

在神经网络中&#xff0c;使用前向或者反向传播计算后&#xff0c;再使用梯度下降去寻找代价函数最小时 θ \theta θ的取值是一个可行的方法&#xff0c;但是它很容易出错&#xff1a;因为在这个算法中含有海量的细节&#xff0c;容易产生微小而又难以察觉的bug。即便是存在bu…

为什么 Serverless 能提升资源利用率?

作者&#xff1a;木吴 阿里云智能高级技术专家 业务的负载往往不是一成不变的&#xff0c;而是随着时间呈现一定的上下波动。传统的应用构建方式一般是备足充分的资源以保障业务可用性&#xff0c;造成资源利用率不高的现象。随着容器技术的普及&#xff0c;应用可以通过弹性伸…