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 建造者调用DSLsearchSourceBuilder.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 ||…接收聚合结果,否则报错。
示例图:

相关文章:
ES在企业项目中的实战总结,彻底掌握ES的使用
通过之前两篇文章 了解了ES的核心概念和基础使用学习进阶的DSL语法处理复杂的查询 这段时间通过在本企业代码中对ES框架的使用,总结了不少经验。主要分为三点 企业封装了ES原生的api,需要使用企业项目提供的接口实现 -------简单使用(本章节目…...
QT的Qporcess功能的使用
具体实现代码如下: #include <QProgressBar>//必须要包含的头文件 #include <QProcess>// 创建一个QProgressBar对象QProgressBar *progressBar new QProgressBar(this);QProcess *proces;process_shownew process;// 设置进度条的最小值和最大值prog…...
【图灵诸葛】jvm笔记
2023年10月23日14:04:44 jvm 1.jdk体系结构图回顾(Av333129672,P1) jdk jre 底层是hotspot jvm 2.java虚拟机内部组成(Av333129672,P2) 堆 方法区 执行引擎 类加载 本地方法栈 线程栈(虚拟机栈) 3.java虚拟机栈讲解(Av333129672,P3) 程序计数器…...
数据安全小课堂开讲啦!看这里!
数据安全小课堂开讲啦!看这里! 1、什么是数据? 《数据安全法》第三条明确,本法所称的数据,就是指任何以电子或者其他方式对信息的记录。小到个人使用手机、电脑等电子产品时浏览的网页、下载的应用、存储的文件&…...
单片机矩阵键盘
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、什么是矩阵键盘?1.独立键盘2.矩阵键盘变化1变化2变化3 3. 通过变型,举一反三,就可以实现4*4的矩阵键盘扫描 二、使用步骤…...
横坐标日期等间隔绘图 python示例代码
有两列数据,一列是日期,另一列是数值。日期是递增的,但是间隔不是均匀的。比如1月1日至2月1日有10组数据,2月1日至3月1日有100组数据,3月1日至4月1日有1000组数据。我想绘折线图,横坐标是日期,纵…...
photoshop2024免费插件Portraiture3
随着手机摄影的普及,修图可以说是现代人的必备生活技能之一了,现在谁发个朋友圈不把自己的照片修的美美的呢?那么如何拥有一张氛围感满满的照片呢?这不得不提图片处理软件中的王牌——photoshop。作为专业的图片处理软件ÿ…...
NewStarCTF2023week4-More Fast(GC回收)
打开链接,存在很多个类,很明显是php反序列化漏洞利用,需要构造pop链 , 关于pop链构造的详细步骤教学,请参考我之前的博客,真的讲得很详细也容易理解: http://t.csdnimg.cn/wMYNB 如果你是刚接…...
和鲸赞助丨第16届中国R会议暨2023 X-AGI大会通知
第16届中国 R 会议暨2023 X-AGI大会将于11月25-30日在中国人民大学召开,探讨数据科学和人工智能的相关进展,本次会议将采用线上会议和线下会议相结合的方式举办。 在过去的15年里,中国R会议一直致力于探讨数据科学在各学科、各行业的探索和实…...
Python第三方库 - Flask(python web框架)
1 Flask 1.1 认识Flask Web Application Framework( Web 应用程序框架)或简单的 Web Framework( Web 框架)表示一个库和模块的集合,使 Web 应用程序开发人员能够编写应用程序,而不必担心协议,线…...
c# sqlite 修改字段类型
因为sqlite不支持直接修改字段类型, 所以只能创建新的表,再将原始数据复制过去。具体操作步骤如下: 第一步, 将表“tableName”的名称修改为 “oldTable” string queryString string.Format("ALTER TABLE {0} RENAME TO …...
[Pytorch] 保存模型与加载模型
1、保存模型 # 定义模型 model BPNetModel(n_featuren_feature,n_hiddenn_hidden,n_outputn_output) #调用网络# 保存模型 torch.save(model, BPNetModel0.pth) 2、加载模型 import torch## 读取模型 model torch.load(BPNetModel0.pth) 3、保存模型参数 #调用网络 mode…...
AES解密报错,Input length must be multiple of 16 when decrypting with padded cipher
# 项目场景:对登录用户名、密码前端加密,后端解密失败 --- # 问题描述 在做login登录页面的用户名和密码加密时,前端加密后端解密,但是抛出`报错:Input length must be multiple of 16 when decrypting with padded cipher`,仔细检查过偏移向量,没有问题,但还是不行,…...
电子学会C/C++编程等级考试2023年05月(三级)真题解析
C/C等级考试(1~8级)全部真题・点这里 第1题:找和为K的两个元素 在一个长度为n(n < 1000)的整数序列中,判断是否存在某两个元素之和为k。 输入 第一行输入序列的长度n和k,用空格分开。 第二行输入序列中的n个整数&am…...
【2023_10_21_计算机热点知识分享】:机器学习中的神经网络
今天的分享主题是机器学习中的神经网络。神经网络是一种模拟人类神经系统的计算模型,它由一系列的神经元组成,每个神经元接收一组输入,经过计算后产生一个输出。神经网络的学习过程是通过调整神经元之间的连接权重来实现的,这个过…...
app开发者提升第四季度广告收入的方法
第四季度将迎来双十一、双十二、圣诞、元旦为主的电商购物季,这是一年中利用线上消费为全新年度和全新预算做好准备的最佳时机,从过往的变现成功案例中汇总了优化要点,帮助开发者在第四季度和未来一年获取更多广告收益。 https://www.shensh…...
#电子电器架构 —— 车载网关初入门
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 PS:小细节,本文字数7000+,详细描述了网关在车载框架中的具体性能设置。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他…...
系统工程利用计算机作为工具
系统工程利用计算机作为工具,对系统的结构、元素、(18)和反馈等进行分析,以达到最优(19)、最优设计、最优管理和最优控制的目的。霍尔(A.D.Hall)于1969年提出了系统方法的三维结构体…...
MathType7.4绿色和谐版数学公式编辑器
MathType 是一个功能强大、所见即所得的数学公式编辑器,可以在 Word、PowerPoint 等办公软件中轻松输入各种复杂的物理公式、化学方程式和符号。由 MathType 创建的公式能与 Office 文档完美结合,显示效果很好;MathType 可在任何支持 OLE 对象…...
JAVA代码审计-纵向越权漏洞分析
查看这个cms系统后台管理员 添加用户的页面 点击添加管理员 这个模块只有管理员拥有,普通用户没有这个模块。 打开源码分析是否存在越权漏洞。 ------------------------------------------------------------------------------------------------------------ …...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
