【ElasticSearch系列-05】SpringBoot整合elasticSearch

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());
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

你了解SonarQube 吗

你了解SonarQube 吗 文章目录 你了解SonarQube 吗一、介绍二、idea代码检测工具SonarLint安装方法使用方法 三、常见的Sonar解决方法Unused "private" fields should be removedSections of code should not be "commented out"Useless imports should be …

使用 C# 在Word中插入图表

Word中的图表功能将数据可视化地呈现在文档中。这为展示数据和进行数据分析提供了一种方便且易于使用的工具&#xff0c;使作者能够以直观的方式传达信息。要通过C#代码来实现在Word中绘制图表&#xff0c;可以借助 Spire.Doc for .NET 控件&#xff0c;具体操作参考下文。 目录…

国内某发动机制造工厂RFID智能制造应用解决方案

一、工厂布局和装备 国内某发动机制造工厂的装配车间布局合理&#xff0c;设备先进&#xff0c;在这个5万平方米的生产区域内&#xff0c;各个工位之间流程紧密&#xff0c;工厂采用了柔性设备&#xff0c;占比达到了67%&#xff0c;数控化率超过90%&#xff0c;自动化率达到了…

【gpt redis】原理篇

用的黑马程序员redis课程的目录&#xff0c;但是不想听讲了。后续都是用gpt文档获取的。 1.课程介绍(Av766995956,P145) 2.Redis数据结构-动态字符串(Av766995956,P146) sds 1M是个界限 其实他是个由c语言实现的结构体 有这么几个参数 len alloc flag char[] len是实际长度 …

Xbox漫游指南

以Xbox series s为例 开机启动 用手柄连接&#xff0c;注意两颗电池要方向相反插入&#xff0c;虽然里面2个插槽长一样&#xff1b; Xbox APP极其难用&#xff0c;放弃&#xff0c;直接用手柄连接 转区 只需要一个空U盘&#xff0c;大小不限制&#xff0c;格式化为NTPS格式…

Oracle-执行计划

执行计划生成的几种方式 1. EXPLAIN FOR 语法&#xff1a; EXPLAIN PLAN FOR SQL语句SELECT * FROM TABLE(dbms_xplan.display());优点&#xff1a; 无需真正执行SQL 缺点&#xff1a; 没有输出相关的统计信息&#xff0c;例如产生了多少逻辑读、物理读、递归调用等情况无法判…

LLM系列 | 26:阿里千问Qwen模型解读、本地部署

引言 简介 预训练 数据来源 预处理 分词 模型设计 外推能力 模型训练 实验结果 部署实测 对齐 监督微调(SFT) RM 模型 强化学习 对齐结果(自动和人工评估) 自动评估 人工评估 部署实测 总结 引言 人生自是有情痴&#xff0c;此恨不关风与月。 ​ 今天这篇小…

系列六、过滤器(二)#案例演示

一、案例演示 说明&#xff1a;如下案例通过springboot的方式演示Filter是如何使用的&#xff0c;以获取Controller中的请求参数为切入点进行演示 1.1、前置准备工作 1.1.1、pom <dependencies><!-- spring-boot --><dependency><groupId>org.spring…

tcp/ip协议2实现的插图,数据结构2 (15 - 章)

(40) 40 十五1 插口层 结构socket,sysent (41) 41 十五2 插口层 实用函数与file结构描述汇总 (42) 42 十五3 插口层 函socket,socreate,pr_usrreq (43)

java毕业设计基于springboot+vue线上教学辅助系统

项目介绍 本论文主要论述了如何使用JAVA语言开发一个线上教学辅助系统 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述线上教学辅助系统的当前背景以及系统开…

【Python基础】Python编程入门自学笔记,基础大全,一篇到底!

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

基于Qt命令行处理XML文件读写

Qt源码在后面,文本介绍Qt国际化语言和XML # XML基础(一) ## 1、概述 ### 1.1 定义(xml是个啥玩意儿?) XML(extensible Markup Language)俗称差妹儿,专业称之为:可拓展标记语言。 (1)何为标记,指的是一种标记语言,或者标签语言,即用一系列的标签来对数据进行…

SSD入门到精通系列-总目录

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《SSD入门到精通系列》 综述&#xff1a; SSD-序 [SSD综述1.1] 导论 [SSD综述1.2] SSD 和 HDD&#xff08;机械硬盘) 区别&#xff1f; 免责声明&#xff1a; 本文根据公开信息整理&#xff0c;旨在介绍更…

layui form 中input输入框长度的统一设置

Layui.form中使用class"layui-input-inline"就可轻松将元素都放到一行&#xff0c;但如果元素过多&#xff0c;就会自动换行。那就需要手动设置input框的长度。 像这种情况&#xff1a; 其实只需要添加css样式就可修改了 .layui-form-item .layui-input-inline {wid…

【牛客网】安全—加密和安全

每日一练 Day1&#xff1a; 1.信息安全的基本属性是&#xff08; D &#xff09; A.保密性 B.完整性 C.可用性&#xff0c;可靠性&#xff0c;可控性 D.A、B、C都是 信息安全的基本属性通常可以归纳为以下几个方面&#xff1a; 保密性&#xff08;Confidentiality&#xf…

Linux学习第28天:Platform设备驱动开发(二): 专注与分散

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 三、硬件原理图分析 四、驱动开发 1、platform设备与驱动程序开发 53 /* 54 * 设备资源信息&#xff0c;也就是 LED0 所使用的所有寄存器 55 */ 56 static str…

自定义SpringBoot启动图标

在SpringBoot项目的resources目录下创建banner.txt文件 在https://www.bootschool.net/网站上复制Ascll艺术字&#xff08;图&#xff09;粘贴到banner.txt中保存。 启动项目就会加载 可以修改颜色&#xff0c;和版本号 ${application.version} 输出版本 ${spring-boot.v…

计网note

其他 未分类文档 CDMA是码分多路复用技术 和CMSA不是一个东西 UPD是只确保发送 但是接收端收到之后(使用检验和校验 除了检验的部分相加 对比检验和是否相等。如果不相同就丢弃。 复用和分用是发生在上层和下层的问题。通过比如时分多路复用 频分多路复用等。TCP IP 应用层的…

uni-app华为审核被拒,驳回原因:您的应用在运行时,未见向用户告知权限申请的目的

华为审核被拒&#xff1a; 您的应用在运行时&#xff0c;未见向用户告知权限申请的目的&#xff0c;向用户索取(相机存)等权限&#xff0c;不符合华为应用市场审核标准。 <uni-popup ref"perpopup" type"center" :mask-clickfalse><view class&qu…

【解锁未来】探索Web3的无限可能-02

文章目录 什么是Web3 &#xff1f;Web3对公司的意义&#xff1f; 什么是Web3 &#xff1f; 简单地说&#xff0c;Web3 是加密货币的延伸&#xff0c;它以新的方式使用区块链来达到新的目的。区块链可以存储钱包中代币的数量、自我执行合同的条款或去中心化应用程序&#xff08;…