ES在企业项目中的实战总结,彻底掌握ES的使用

通过之前两篇文章

  • 了解了ES的核心概念和基础使用
  • 学习进阶的DSL语法处理复杂的查询

这段时间通过在本企业代码中对ES框架的使用,总结了不少经验。主要分为三点

  • 企业封装了ES原生的api,需要使用企业项目提供的接口实现 -------简单使用(本章节目的)
  • 项目会遇到更复杂的查询需求,需要进一步深入对ES的学习 -------复杂使用
  • 了解项目如何封装原生的api,学习设计思想 --------深入学习

目录

  • 1. Term查询
    • 1.1 原生api实现term查询
    • 1.2 企业api实现term查询
  • 2. 复合查询__must
    • 2.1 原生api实现must查询
    • 2.2 企业api实现must查询
  • 3. 复合查询__should
  • 4. 复合查询__mustnot
  • 5. 分页和排序
    • 5.1 原生api实现分页和排序
    • 5.2 企业api实现分页和排序
  • 6 聚合查询
    • 6.1 原生api实现桶聚合
    • 6.2 企业api实现桶聚合

------------------------------本章节核心目的是梳理出 本企业项目提供的api原生ES提供的api 的使用区别--------------------------------





本企业将ES的api大致封装成了两个核心类
EsOperater类

方法说明
String[] indexes()
Integer from()分页
Integer size()分页
List sort()排序
QueryBuilder queryBuilder()普通查询/复合查询
EsOperaterBuiler esOperaterBuiler()继承类
SearchResponse execute()执行查询
CountResponse queryTotal()
SearchResponse executeScroll()
QueryBuilder buildQueryBuilder()
QueryBuilder buildQueryBuilderByQueryType(EsQueryInfoBean queryInfo)根据查询信息bean构造相应的查询器
List buildAggBuilder()根据aggMap创建聚合器,包括单层聚合和多层聚合
AggregationBuilder makeChildAgg(EsAggInfoBean esAggInfo, EsAggInfoBean parentAggInfo)递归创建聚合器
EsOperater build()

EsOperaterBuiler类(重点关注)

方法说明
EsOperaterBuiler indexes(String… indexes)设置索引集合
EsOperaterBuiler from(Integer from)设置分页参数的查询数量
EsOperaterBuiler size(Integer size)设置分页参数的查询数量
EsOperaterBuiler sort(String sort)设置排序字段
EsOperaterBuiler sortOrder(SortOrder sortOrder)设置排序排序方式(升序、降序)
EsOperaterBuiler queryBuilder(QueryBuilder queryBuilder)设置查询构建器(QueryBuilder),如果操作构建器(EsOperater)中buildQueryBuilder()方法构造不出需要的查询构建起,
Boolean isAliasExists(String indexName)查询别名是否存在

1. Term查询

1.1 原生api实现term查询

@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
    // 2. 构建DSL
    	// 2.1 获取建造者
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		// 2.2 建造者调用DSL
    searchSourceBuilder.termQuery("name","zjh");
    	// 2.3 组装
    request.source(searchSourceBuilder);
  
    	// 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    	// 4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }
    
}

此时就可以获取到source的数据了。上述写法也可以简化,如下

// 此方式常用
@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
	// 2. 构建DSL语句
    request.source().query(QueryBuilders.termQuery("name","zjh"));
    
    // 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    // 4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }
    
}

1.2 企业api实现term查询

@Test
void TermQuery(){
    // 构建索引名称
    String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;
    
    // 1. 设置索引集合
    EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);
    
    // 2. 设置查询构建器 + 准备DSL语句
    builder.queryBuilder(QueryBuilders.termQuery("name","zjh"));
    
    // 3. 发送请求
    SearchResponse response = builder.build().execute();
    
    //  4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }

}

解释:

步骤一:需要将 索引名 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用

步骤二:需要将 DSL语句 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用

步骤三:需要从esOperaterBuiler类 切换到 esOperater类,再执行最核心的 execute() 方法,这个方法会进行一些列操作,将最终的结果返回给 response

2. 复合查询__must

2.1 原生api实现must查询

@Test
void MustQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
	// 2. 构建DSL语句
    	// 2.1 创建bool查询
    	BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    	// 2.2 添加must条件
        boolQuery.must(QueryBuilders.termQuery("name", "zjh"));
 		// 2.3 构建请求内容
   		request.source().query(boolQuery);
    
    // 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    // 4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }
    
}

2.2 企业api实现must查询

@Test
void TermQuery(){
    // 构建索引名称
    String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;
    
    // 1. 设置索引集合
    EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);
    
    // 2. 设置查询构建器 + 准备DSL语句
    	// 2.1 创建bool查询
    	BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    	// 2.2 添加must条件
        boolQuery.must(QueryBuilders.termQuery("name", "zjh"));
    	// 此行代码的作用就是将构造的must条件,存放到EsOperater类的全局变量
    	builder.queryBuilder(boolQuery);
    
    // 3. 发送请求
    SearchResponse response = builder.build().execute();
    
    //  4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }

}
解释一下步骤二:
    可能会疑惑为什么不这样写
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    BoolQueryBuilder mustQuery = boolQuery.must(QueryBuilders.termQuery("name", "zjh"));
    builder.queryBuilder(mustQuery);

	因为must(参数)底层会将参数传给boolQuery.must()的boolQuery对象,是递增的逻辑

解释:

步骤一:需要将 索引名 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用

步骤二:需要将 DSL语句(布尔查询) 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用

步骤三:需要从esOperaterBuiler类 切换到 esOperater类,再执行最核心的 execute() 方法,这个方法会进行一些列操作,将最终的结果返回给 response

可以进一步简化

@Test
void TermQuery(){
    // 构建索引名称
    String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;
    
    // DSL语句
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    boolQuery.must(QueryBuilders.termQuery("name", "zjh"));
    
    // 使用企业api实现查询
    EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler();
    
    SearchResponse response = builder.index(indexName).queryBuilder(boolQuery).build().execute();
   
    //  4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }

}

3. 复合查询__should

同理

4. 复合查询__mustnot

同理

5. 分页和排序

5.1 原生api实现分页和排序

// 此方式常用
@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
		//2.查询__构建DSL语句
    	request.source().query(QueryBuilders.termQuery("name","zjh"));
    
    	//  分页
    	request.source().from.size(5);
    
    	//  时间排序
    	request.source().sort(“logTime”,SortOrder.ASC);
    
    // 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    // 4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }
    
}

5.2 企业api实现分页和排序

@Test
void TermQuery(){
    // 构建索引名称
    String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;
    
    // 1. 设置索引集合
    EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);
    
    // 2. 查询
    builder.queryBuilder(QueryBuilders.termQuery("name","zjh"));
    
    //  分页
    builder.queryBuilder(QueryBuilders.termQuery("name","zjh")).size(5);
    
    //  排序
    builder.queryBuilder(QueryBuilders.termQuery("name","zjh")).sort("logTime").sortOrder(SortOrder.DESC);
    
    // 3. 发送请求
    SearchResponse response = builder.build().execute();
    
    //  4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }

}

6 聚合查询

6.1 原生api实现桶聚合

// 需求:实现对城市、品牌的聚合。即用户输入城市、品牌,得到搜索结果
@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
	//2.查询
    	// CityName:自定义桶名; city:根据城市聚合
     	AggregationBuilder aggregationBuilder1 = AggregationBuilders.terms("CityName").field("city");
    	AggregationBuilder aggregationBuilder2 = AggregationBuilders.terms("BrandName").field("brand");
    	
    	request.source().aggregation(aggregationBuilder1);
    	request.source().aggregation(aggregationBuilder2);
    
    // 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    // 4. 解析数据
    Aggreagtions aggreagtions = response.getAggreagtions();
    List<? extends Terms.Bucket> buckets1 =  aggreagtions.get("CityName").getBuckets();
    for (Terms.Bucket bucket : buckets) {
       //打印结果是:西安 或者 上海
       System.out.println(bucket.getKeyAsString());
     }
    
     List<? extends Terms.Bucket> buckets2 =  aggreagtions.get("BrandName").getBuckets();
    for (Terms.Bucket bucket : buckets) {
       //打印结果是:星巴克 或者 瑞幸
       System.out.println(bucket.getKeyAsString());
     }
    
}

6.2 企业api实现桶聚合

// 需求:实现对城市、品牌的聚合。即用户输入城市、品牌,得到搜索结果
@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
	//2.查询
   	List<AggregationBuilder> aggregationBuilderList = new ArrayList<>();
    aggregationBuilderList.add(AggregationBuilders.terms("CityName").field("city"));;
    aggregationBuilderList.add(AggregationBuilders.terms("BrandName").field("brand"));
    // aggBuilderList()企业封装的工具,将聚合参数赋值到全局变量上
    builder.aggBuilderList(aggregationBuilderList);

    
    // 3. 发送请求
    SearchResponse response = builder.size(1).build().execute();
    
    // 4. 解析数据
    Aggreagtions aggreagtions = response.getAggreagtions();
    // 注意ParsedStringTerms,还有ParsedLongTerms、ParsedDoubleTerms...
    ParsedStringTerms CityName =  aggreagtions.get("CityName");
    
    for (Terms.Bucket bucket : CityName.getBuckets()) {
       //打印结果是:西安 或者 上海
       System.out.println(bucket.getKeyAsString());
     }
    
    ParsedStringTerms BrandName =  aggreagtions.get("BrandName");
    for (Terms.Bucket bucket : BrandName.getBuckets()) {
       //打印结果是:星巴克 或者 瑞幸
       System.out.println(bucket.getKeyAsString());
     }
    
}

这里需要解释一下步骤四中的 ParsedStringTerms

ES会将聚合结果封装到特定的类中,方便你来处理不同类型的聚合结果。

ParsedLongTerms:

  • 这个类用于处理长整型(long)类型的聚合结果。

ParsedStringTerms:

  • 这个类用于处理字符串(String)类型的聚合结果。

什么意思呢?在ES中对"CityName"进行聚合。

返回结果中可以看到如下信息,表示星巴克有三家(西安)

  • key:“星巴克” (字符串类型)

  • doc_count : 3 (long类型)

因此根据key的类型,正确选择使用ParsedStringTerms || ParsedLongTerms ||…接收聚合结果,否则报错。

示例图:
在这里插入图片描述

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

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

相关文章

论文阅读[51]通过深度学习快速识别荧光组分

【论文基本信息】 标题&#xff1a;Fast identification of fluorescent components in three-dimensional excitation-emission matrix fluorescence spectra via deep learning 标题译名&#xff1a;通过深度学习快速识别 三维激发-发射矩阵荧光光谱中的荧光组分 期刊与年份&…

基于springboot的房产销售系统

基于springbootvue的房产销售系统 角色&#xff1a;用户、管理员、销售经理 管理员&#xff1a;首页、个人中心、用户管理、销售经理管理、房源信息管理、房源类型管理、房子户型管理、交易订单管理、预约看房管理、评价管理、我的收藏管理、系统管理等。 用户:首页、个人中心…

UI 自动化测试框架:PO模式+数据驱动

1. PO 设计模式简介 什么是 PO 模式&#xff1f; PO&#xff08;PageObject&#xff09;设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成一个 Page 类&#xff0c;并以页面为单位来写测试用例&#xff0c;实现页面对象和测试用例的分离。 PO 模式的设计思想与…

利用Jpom在线构建Spring Boot项目

1 简介 前面介绍了运用Jpom构建部署Vue项目&#xff0c;最近研究了怎么部署Spring Boot项目&#xff0c;至此&#xff0c;一套简单的前后端项目就搞定了。 2 基本步骤 因为就是一个简单的自研测试项目&#xff0c;所以构建没有使用docker容器&#xff0c;直接用java -jar命令…

xcode15一直显示正在连接iOS17真机问题解决

前言 更新xcode15之后&#xff0c;出现了各种报错问题&#xff0c;可谓是一路打怪啊&#xff0c;解决一个报错问题又来一个。没想到到了最后还能出现一个一直显示正在连接iOS17真机的问题 一直显示正在连接iOS17真机的问题 问题截图如下&#xff1a; 解决方法 1. 打开De…

2018年亚太杯APMCM数学建模大赛B题人才与城市发展求解全过程文档及程序

2018年亚太杯APMCM数学建模大赛 B题 人才与城市发展 原题再现 招贤纳士是过去几年来许多城市的亮点之一。北京、上海、武汉、成都、西安、深圳&#xff0c;实际上都在用各种吸引人的政策来争夺人才。人才代表着城市创新发展的动力&#xff0c;因为他们能够在更短的时间内学习…

Kafka入门04——原理分析

目录 01理解Topic和Partition Topic(主题) Partition(分区) 02理解消息分发 消息发送到分区 消费者订阅和消费指定分区 总结 03再均衡(rebalance) 再均衡的触发 分区分配策略 RangeAssignor(范围分区) RoundRobinAssignor(轮询分区) StickyAssignor(粘性分区) Re…

【多线程】Java如何实现多线程?如何保证线程安全?如何自定义线程池?

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 多线程 Java多线程1. 进程与线程2. 多线程1&am…

脏牛提权 liunx

使用方法 Liunx 普通用户 内核版本 在版本里 我直接脏牛提权 有脚本查看内核版本 上传c脚本 编译 直接执行 获取高权限 提权 Liunx https://github.com/InteliSecureLabs/Linux Exploit Suggester 运行这个脚本 上传到客户端 https://github…

小插曲 -- 使用Visual Studio Code远程连接香橙派

在之前的学习中&#xff0c;代码的修改和保存都依赖于“vi”指令&#xff0c;而不得不承认vi指令的编辑界面非常原始&#xff0c;所以&#xff0c;如果可以将代码编辑放到更友好的环境里进行无疑是一件大快人心的事情。 本节介绍如何通过Visual Studio Code来进行远程连接: Vi…

二进制搭建 Kubernetes+部署网络组件+部署CornDNS+负载均衡部署+部署Dashboard

二进制搭建 Kubernetes v1.20 k8s集群master01&#xff1a;20.0.0.50 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集群master02&#xff1a;20.0.0.100k8s集群node01&#xff1a;20.0.0.110 kubelet kube-proxy docker etcd k8s集群node02&#xff1a;20.…

SysTick—系统定时器

SysTick 简介 SysTick—系统定时器是属于CM3内核中的一个外设&#xff0c;内嵌在NVIC中。系统定时器是一个24bit 的向下递减的计数器&#xff0c;计数器每计数一次的时间为1/SYSCLK&#xff0c;一般我们设置系统时钟SYSCLK 等于72M。当重装载数值寄存器的值递减到0的时候&#…

研发效能(DevOps)职业技术认证-第六期开班啦丨IDCF

本证书是由国家工业和信息化部教育与考试中心颁发的职业技术证书&#xff0c;也是国内首个《研发效能&#xff08;DevOps&#xff09;工程师职业技术认证》。该《认证》对研发效能&#xff08;DevOps&#xff09;工程师的职业技术分为初级、中级、高级三个专业等级。 IDCF社区…

商场巨变!拓世法宝AI智能商业一体机引爆智慧购物新浪潮

在如今信息爆炸的时代&#xff0c;大型商场的规模与复杂程度也呈现出愈发庞大的趋势。它的背后不仅是商场规模的扩大&#xff0c;更是商业模式的转型升级。消费者对于购物体验和服务质量的要求也日益提高。传统商场单一提供商品销售的职能已无法满足消费者多元化的需求&#xf…

wf-docker集群搭建(未完结)

系列文章目录 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、redis集群二、mysql集群三、nacos集群1. 环境要求2. 拉取镜像2.1. 拉取镜像方式配置集群2.2. 自定义nacos镜像配置集群 3 自定义…

基于windows10的pytorch环境部署及yolov8的安装及测试

第一章 pytorch环境部署留念 第一步&#xff1a;下载安装anaconda 官网地址 &#xff08;也可以到清华大学开源软件镜像站下载&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/&#xff09; 我安装的是下面这个&#xff0c;一通下一步就完事儿。 第二步…

EtherCAT从站转CclinkIE协议网关应用案例

远创智控的YC-ECT-CCLKIE网关&#xff0c;一款具有强大功能的ETHERCAT通讯网关。 它可以将ETHERCAT网络和CCLINK IE FIELD BASIC网络无缝连接起来。作为ETHERCAT总线中的从站&#xff0c;本网关可以接收来自ETHERCAT主站的数据&#xff0c;并将其传输到CCLINK IE FIELD BASIC网…

高效MMdetection(3.1.0)环境安装和训练自己数据集教程(实现于Linux(ubuntu),可在windows尝试)

一、前言 很久没用mmdetection了&#xff0c;作为目标检测常见的几个深度学习框架&#xff0c;mmdetection用的人还是很多的&#xff0c;其中比较吸引人的一点就是mmdetection集成了非常多的算法&#xff0c;对于想做实验对比和算法学习的人来说&#xff0c;基于这个框架可以事…

cola架构:cola源码中访问者模式应用浅析

目录 1.访问者模式简介 2.cola访问者模式应用 2.1 cola被访问者类图 2.2 cola访问者类图 我们知道&#xff0c;如果一个对象结构包含很多类型的对象&#xff0c;希望对这些对象实施一些依赖其具体类型的操作&#xff0c;但又避免让这些操作“污染”这些对象的类&#xff0c…

day50 --动态规划9

198.打家劫舍 213.打家劫舍II 337.打家劫舍III 第一题&#xff1a;打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一…
最新文章