【ElasticSearch系列-05】SpringBoot整合elasticSearch

news2024/11/28 17:50:31

ElasticSearch系列整体栏目


内容链接地址
【一】ElasticSearch下载和安装https://zhenghuisheng.blog.csdn.net/article/details/129260827
【二】ElasticSearch概念和基本操作https://blog.csdn.net/zhenghuishengq/article/details/134121631
【三】ElasticSearch的高级查询Query DSLhttps://blog.csdn.net/zhenghuishengq/article/details/134159587
【四】ElasticSearch的聚合查询操作https://blog.csdn.net/zhenghuishengq/article/details/134159587
【五】SpringBoot整合elasticSearchhttps://blog.csdn.net/zhenghuishengq/article/details/134212200

SpringBoot整合elasticSearch

  • 一,SpringBoot整合ElasticSearch
    • 1,需要的依赖以及版本
    • 2,创建config配置类并测试连接
    • 3,增删改查测试
      • 3.1,索引插入数据
      • 3.2,根据id查询数据
      • 3.3,删除一条数据
    • 4,普通查询
      • 4.1,match条件查询
      • 4.2,term精确匹配
      • 4.3,prefix前缀查询
      • 4.4,通配符查询wildcard
      • 4.5,范围查询
      • 4.6,fuzzy模糊查询
      • 4.7,highlight高亮查询
    • 5,聚合查询
      • 5.1,aggs聚合查询
      • 5.2,获取最终结果

一,SpringBoot整合ElasticSearch

前面几篇讲解了es的安装,dsl语法,聚合查询等,接下来这篇主要就是讲解通过java的方式来操作es,这里选择通过springboot的方式整合ElasticSearchSearch

在学习这个整合之前,可以查看对应的官网资料:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/7.17/connecting.html

1,需要的依赖以及版本

首先创建springboot项目,然后需要的依赖如下,我前面用的是7.7.0的版本,因此这里继续使用这个版本。其他的依赖根据个人需要选择

<properties>
    <java.version>8</java.version>
    <elasticsearch.version>7.7.0</elasticsearch.version>
</properties>
<dependencies>
	<dependency>
	    <groupId>org.elasticsearch.client</groupId>
	    <artifactId>elasticsearch-rest-high-level-client</artifactId>
	    <version>7.7.0</version>
	</dependency>
</dependencies>

2,创建config配置类并测试连接

随后创建一个config的配置类,用于连接上ElasticSearch,我这边是单机版,并没有集群

/**
 * 连接es的工具类
 */
@Configuration
public class ElasticSearchConfig { 
    public static final RequestOptions COMMON_OPTIONS;
    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
        COMMON_OPTIONS = builder.build();
    }
    @Bean
    public RestHighLevelClient esRestClient(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("xx.xx.xx.xx", 9200, "http")));
        return  client;
    }
}

在创建好了之后,可以直接在test类中进行测试,看能否连接成功

@RunWith(SpringRunner.class)
@SpringBootTest
public class StudyApplicationTests {
    @Resource
    private RestHighLevelClient client;

    @Test
    public void contextLoads() {
        System.out.println(restHighLevelClient);
    }
}

在运行之后,如果打印出了以下这句话,表示整合成功

org.elasticsearch.client.RestHighLevelClient@7d151a

3,增删改查测试

3.1,索引插入数据

首先先创建一个users的索引,并向里面插入一条数据。插入和更新都可以用这个方法

//创建一个user索引,并且插入一条数据
@Test
public void addData() throws IOException {
    //创建一个索引
    IndexRequest userIndex = new IndexRequest("users");
    User user = new User();
    user.setId(1);
    user.setUsername("Tom");
    user.setPassword("123456");
    user.setAge(18);
    user.setSex("女");
   //添加数据
   userIndex.source(JSON.toJSONString(user), XContentType.JSON);
   IndexResponse response = client.index(userIndex, ElasticSearchConfig.COMMON_OPTIONS);
	//响应数据
	System.out.println(response);
}

随后再在kibana中查询这个索引,可以看到这条数据是已经插入成功的,并且索引页创建成功

在这里插入图片描述

3.2,根据id查询数据

查询id为1的数据,需要通过QueryBuild构造器查询

@Test
public void getById() throws IOException {
    SearchRequest request = new SearchRequest("users");
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.matchQuery("id", "1"));
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    System.out.println(response);
}

3.3,删除一条数据

删除刚刚创建的这条数据,这里直接设置id为1即可

@Test
public void deleteById() throws Exception{
    DeleteRequest request = new DeleteRequest("users");
    request.id("1");
    DeleteResponse delete = client.delete(request, ElasticSearchConfig.COMMON_OPTIONS);
    System.out.println(delete);
}

4,普通查询

这里主要是结合本人写的第三篇Query DSL的语法,通过java的方式写出依旧是先创建一个员工的信息索引,并且设置字段得我属性

PUT /employees
{
  "mappings": {
    "properties": {
      "name":{
        "type": "keyword"
      },
      "job":{
        "type": "keyword"
      },
      "salary":{
        "type": "integer"
      }
    }
  }
}

随后批量的插入10条数据

PUT /employees/_bulk
{ "index" : {  "_id" : "1" } }
{ "name" : "huisheng1","job":"python","salary":35000 }
{ "index" : {  "_id" : "2" } }
{ "name" : "huisheng2","job":"java","salary": 50000}
{ "index" : {  "_id" : "3" } }
{ "name" : "huisheng3","job":"python","salary":18000 }
{ "index" : {  "_id" : "4" } }
{ "name" : "huisheng4","job":"java","salary": 22000}
{ "index" : {  "_id" : "5" } }
{ "name" : "huisheng5","job":"javascript","salary":18000 }
{ "index" : {  "_id" : "6" } }
{ "name" : "huisheng6","job":"javascript","salary": 25000}
{ "index" : {  "_id" : "7" } }
{ "name" : "huisheng7","job":"c++","salary":20000 }
{ "index" : {  "_id" : "8" } }
{ "name" : "huisheng8","job":"c++","salary": 20000}
{ "index" : {  "_id" : "9" } }
{ "name" : "huisheng9","job":"java","salary":22000 }
{ "index" : {  "_id" : "10" } }
{ "name" : "huisheng10","job":"java","salary": 9000}

4.1,match条件查询

首先是分页查询,分页查询的queryDSL的语法如下

GET /employees/_search
{
  "query": {
    "match": {
      "job": "java"
    }
  }
}

java的语法如下

SearchRequest request = new SearchRequest("employees");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchQuery("job", "java"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println(response);

短语匹配的语法如下

builder.query(QueryBuilders.matchPhraseQuery("job","java"));

多字段查询的语法如下

String fields[] = {"job","name"};
builder.query(QueryBuilders.multiMatchQuery("java",fields));

queryString的语法如下

builder.query(QueryBuilders.queryStringQuery("java"));

4.2,term精确匹配

GET /employees/_search
{
  "query": {
    "term": {
      "job": "java"
    }
  }
}

精确匹配通过java的方式如下

builder.query(QueryBuilders.termQuery("job","java"));

4.3,prefix前缀查询

PUT /employees/_search
{
    "query":{
        "prefix":{
            "name":{
                "value":"huisheng1"
            }
        }
    }
}

前缀查询的java方式如下

builder.query(QueryBuilders.prefixQuery("name","huisheng1"));

4.4,通配符查询wildcard

GET /employees/_search
{
  "query": {
    "wildcard": {
      "job": {
        "value": "*py*"
      }
    }
  }
}

通配符查询的java方式如下

builder.query(QueryBuilders.wildcardQuery("job","py"));

4.5,范围查询

POST /employees/_search
{
  "query": {
    "range": {
      "salary": {
        "gte": 25000
      }
    }
  }
}

范围查询的java方式如下

builder.query(QueryBuilders.rangeQuery("salary").gte(25000));

4.6,fuzzy模糊查询

GET /employees/_search
{
  "query": {
    "fuzzy": {
      "job": {
        "value": "javb",
        "fuzziness": 1    //表示允许错一个字
      }
    }
  }
}

模糊查询的java方式如下

builder.query(QueryBuilders.fuzzyQuery("job","javb").fuzziness(Fuzziness.ONE));

4.7,highlight高亮查询

GET /employees/_search
{
  "query": {
    "term": {
      "job": {
        "value": "java"
      }
    }
  },
  "highlight": {
    "fields": {
      "*":{}
    }
  }
}

高亮查询的java方式如下

builder.query(QueryBuilders.termQuery("job","java"));
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("job");
builder.highlighter(highlightBuilder);

5,聚合查询

5.1,aggs聚合查询

先通过job进行分组查询,再拿到结果后再进行stats查询,求最大值,最小值,平均值等

POST /employees/_search
{
  "size": 0,
  "aggs": {
    "name": {
      "terms": {
        "field": "job"
      },
      "aggs": {
        "stats_salary": {
          "stats": {
            "field": "salary"
          }
        }
      }
    }
  }
}

其java代码如下,需要注意的点就是,如果存在二级聚合,那么需要调用这个 subAggregation 方法,如果只需要聚合的结果而不需要查询的结果,可以直接在SearchSourceBuilder的实例设置为0即可。

@Test
public void toAgg() throws  Exception{
    //创建检索请求
    SearchRequest searchRequest = new SearchRequest();
    //指定索引
    searchRequest.indices("employees");
    //构建检索条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    //构建聚合条件
    TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("jobData").field("job");
        aggregationBuilder.subAggregation(AggregationBuilders.stats("salaryData").field("salary"));
	//将聚合条件加入到检索条件中
	builder.aggregation(aggregationBuilder);
	//只要聚合的结果,不需要查询的结果
	builder.size(0);
	searchRequest.source(builder);
	//执行检索
	SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    System.out.println("检索结果:" + searchResponse);
}

打印的结果如下,和预期要打印的结果是一致的

{"took":4,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":10,"relation":"eq"},"max_score":null,"hits":[]},"aggregations":{"sterms#jobData":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"java","doc_count":4,"stats#salaryData":{"count":4,"min":9000.0,"max":50000.0,"avg":25750.0,"sum":103000.0}},{"key":"c++","doc_count":2,"stats#salaryData":{"count":2,"min":20000.0,"max":20000.0,"avg":20000.0,"sum":40000.0}},{"key":"javascript","doc_count":2,"stats#salaryData":{"count":2,"min":18000.0,"max":25000.0,"avg":21500.0,"sum":43000.0}},{"key":"python","doc_count":2,"stats#salaryData":{"count":2,"min":18000.0,"max":35000.0,"avg":26500.0,"sum":53000.0}}]}}}

除了上面的state求全部的最大值,最小值等,还可以分别的求最大值,最小值,平均值,个数等,求平均值的的示例如下,需要使用到这个 AvgAggregationBuilder 构造器

AvgAggregationBuilder avgAggregationBuilder = AggregationBuilders.avg("salaryData").field("salary");
//将聚合条件加入到检索条件中
builder.aggregation(avgAggregationBuilder);

求最大值的示例如下,需要使用到这个 MaxAggregationBuilder 构造器

MaxAggregationBuilder maxAggregationBuilder = AggregationBuilders.max("maxData").field("salary");
//将聚合条件加入到检索条件中
 builder.aggregation(maxAggregationBuilder);

求最小值的示例如下,需要使用到这个 MinAggregationBuilder 构造器

MinAggregationBuilder minAggregationBuilder = AggregationBuilders.min("minData").field("salary");
//将聚合条件加入到检索条件中
builder.aggregation(minAggregationBuilder);

求总个数的示例如下,需要使用到这个 ValueCountAggregationBuilder 构造器

ValueCountAggregationBuilder countBuilder = AggregationBuilders.count("countData").field("salary");
//将聚合条件加入到检索条件中
builder.aggregation(countBuilder);

5.2,获取最终结果

上面在查询之后,会获取 SearchResponse 的对象,这里面就值执行查询后返回的结果

SearchResponse searchResponse

随后可以直接过滤结果,通过for循环去遍历这个 getHits

SearchHits hits = searchResponse.getHits();
SearchHit[] searchHits = hits.getHits();
for (SearchHit searchHit : searchHits) {
    String sourceAsString = searchHit.getSourceAsString();
    Employees employees = JSON.parseObject(sourceAsString, Employees.class);
    System.out.println(employees);

}

或者直接获取聚合操作结果的值

//获取jobData聚合。还有Avg、Max、Min等
Terms maxData = aggregations.get("jobData");
for (Terms.Bucket bucket : maxData.getBuckets()) {
	String keyAsString = bucket.getKeyAsString();
	System.out.println("job职业:" + keyAsString + " 数量==> " + bucket.getDocCount());
}

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

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

相关文章

从科幻走向现实,LLM Agent 做到哪一步了?

LLM 洪流滚滚&#xff0c;AI 浪潮席卷全球&#xff0c;在这不断冲击行业认知的一年中&#xff0c;Agent 以冉冉新星之态引起开发者侧目。OpenAI 科学家 Andrej Karpathy 曾言“OpenAI 在大模型领域快人一步&#xff0c;但在 Agent 领域&#xff0c;却是和大家处在同一起跑线上。…

ESP-07S烧写固件记录

一&#xff0c;固件版本。 下面是官方默认AT指令版本&#xff0c;ESP-07S 的flash大小是4MB。 AT固件汇总 | 安信可科技 (ai-thinker.com) 二&#xff0c;烧录工具。 开发工具清单 | 安信可科技 (ai-thinker.com) 三&#xff0c;下载工具及连线。 使用USB转串口工具。 四&am…

如何将立创EDA中的元器件封装快速导入到AD软件中去

在使用AD软件画PCB的时候&#xff0c;最费时间的就是找元器件的封装。有的元器件如果库里面没有封装的话还得自己手动画&#xff0c;这样会浪费很多时间。 由于立创EDA里面的元器件比较全&#xff0c;而且好多器件都带有封装。那么就可以直接将立创EDA中元器件的封装直接导入到…

项目管理工具有哪些?项目管理必备的6款软件推荐!

在现代商业环境中&#xff0c;项目管理已经成为一个不可或缺的工作流程。有效的项目管理可以提高团队的协作效率&#xff0c;促进任务分配和沟通&#xff0c;并确保项目按时交付。然而&#xff0c;随着项目越来越复杂和多样化&#xff0c;需要使用适合的软件工具来支持项目管理…

并发编程(线程基础)

线程和进程的区别并发与并行的区别线程创建方式runnable和callable的区别run()和start()的区别线程包括哪些状态&#xff0c;状态之间如何变化新建三个线程&#xff0c;如何按顺序执行notify()和notifyAll()的区别wait和sleep方法的区别如何停止一个正在运行的线程 一、线程和进…

保存修改后的图形化配置文件

37.4.5 保存修改后的图形化配置文件 如果使用 V2.4 以前的底板&#xff0c;用的是 LAN8720A 这颗 PHY 芯片&#xff0c;我们在修改网络驱动的时 候我们通过图形界面使能了 LAN8720A 的驱动&#xff0c;使能以后会在.config 中存在如下代码&#xff1a; CONFIG_SMSC_PHYy 打开 d…

基于RK3568的新能源储能能量管理系统ems

新能源储能能量管理系统&#xff08;EMS&#xff09;是一种基于现代化技术的系统&#xff0c;旨在管理并优化新能源储能设备的能量使用。 该系统通过监测、调度和控制新能源储能设备来确保能源的高效利用和可持续发展。 本文将从不同的角度介绍新能源储能能量管理系统的原理、…

idea个性设置

这种灰色代码连在一起

完美处理 Android App 的 apk 输出路径与文件名

实现代码 buildTypes {// ...applicationVariants.all {variant ->variant.outputs.all {Calendar calendar Calendar.getInstance(Locale.CHINA);def buildDate String.format(Locale.CHINA, "%04d%02d%02d", calendar.get(Calendar.YEAR), calendar.get(Cale…

Telnet/ssh/Serial远程工具WindTerm

Telnet/ssh/Serial远程工具WindTerm 一、WindTerm 概述二、WindTerm 下载 一、WindTerm 概述 在远程终端工具中&#xff0c;secureCrt 和 XShell 是两款比较有名的远程工具&#xff0c;但收费。上一篇文章就介绍了一款免费软件MobaXterm&#xff0c;但菜单都是英文的&#xff0…

Doris:StreamLoad导入数据

目录 1.基本原理 2.支持数据格式 3.StreamLoad语法 3.1.请求参数 3.2.返回参数 4.StreamLoad实践 4.1.使用 curl命令 4.2.使用Java代码 Stream load 是一个同步的导入方式&#xff0c;用户通过发送 HTTP 协议发送请求将本地文件或数据流导入到 Doris 中。Stream load 主…

图片有水印怎么去?这三招轻松去除图片水印

当我们在网站找一些的图片做头像或者壁纸的时候&#xff0c;会发现一些好看的图片上会带有一些平台水印&#xff0c;这些水印影响了整张照片的美观&#xff0c;那么图片有水印怎么去呢&#xff1f;这时就需要借用图片处理工具来操作。那你们知道图片有水印怎么去吗?今天我就来…

LCR 166.珠宝的最高价值 + 动态规划 + 记忆化搜索 + 递推 + 空间优化

LCR 166. 珠宝的最高价值 - 力扣&#xff08;LeetCode&#xff09; 现有一个记作二维矩阵 frame 的珠宝架&#xff0c;其中 frame[i][j] 为该位置珠宝的价值。拿取珠宝的规则为&#xff1a; 只能从架子的左上角开始拿珠宝每次可以移动到右侧或下侧的相邻位置到达珠宝架子的右下…

匪夷所思,spring aop这么写竟然会失效!!

背景 spring 版本&#xff1a;3.2.8.RELEASEJDK版本&#xff1a;1.8本地是正常&#xff0c;线上环境是有问题的 应用从云下迁移到云上的过程中出现了一个应用部分aop 通知失效的问题&#xff0c;场景如下&#xff1a; node1 节点上的category 是失效的&#xff0c;element是正…

ubuntu 分区 方案

ubuntu 分区 方案 自动分区啥样子的&#xff1f; 手动分区 需要怎么操作&#xff1f; 注意点是啥&#xff1f; swap分区 要和 内存大小 差不多 安装ubuntu系统时硬盘分区方案 硬盘分区概述 一块硬盘最多可以分4个主分区&#xff0c;主分区之外的成为扩展分区。硬盘可以没有…

C++--二叉搜索树初阶

前言&#xff1a;二叉搜索树是一种常用的数据结构&#xff0c;支持快速的查找、插入、删除操作&#xff0c;C中map和set的特性也是以二叉搜索树作为铺垫来实现的&#xff0c;而二叉搜索树也是一种树形结构&#xff0c;所以&#xff0c;在学习map和set之前&#xff0c;我们先来学…

学习率设置

在我们刚刚接触深度学习时&#xff0c;对学习率只有一个很基础的认知&#xff0c;当学习率过大的时候会导致模型难以收敛&#xff0c;过小的时候会收敛速度过慢&#xff0c;其实学习率是一个十分重要的参数&#xff0c;合理的学习率才能让模型收敛到最小点而非局部最优点或鞍点…

学 Java 怎么进外企?

作者&#xff1a;**苍何&#xff0c;CSDN 2023 年 实力新星&#xff0c;前大厂高级 Java 工程师&#xff0c;阿里云专家博主&#xff0c;土木转码&#xff0c;现任部门技术 leader&#xff0c;专注于互联网技术分享&#xff0c;职场经验分享。 &#x1f525;热门文章推荐&#…

HNU程序设计 练习三-控制结构

1.台球游戏 【问题描述】 在本台球游戏中&#xff0c;包含多种颜色的球&#xff0c;其中&#xff1a;红球15只各1分、黄球1只2分、绿球1只3分、咖啡球1只4分、蓝球1只5分、粉球1只6分、黑球1只7分。 球的颜色表示为&#xff1a; r-红色球 y-黄色球 g-绿色球 c-咖啡色球 b-蓝色…

闭循环低温恒温器的使用注意事项

与液氮恒温器相比&#xff0c;闭循环低温恒温器显得稍微复杂一些&#xff01;这主要表现在组成部分、体积重量、使用操作、升降温时间等方面。闭循环低温恒温器主要由冷头、氦压缩机、两根氦气连管组成&#xff0c;配套设备还有控温仪、真空泵&#xff0c;可能还有循环水冷机。…