当前位置: 首页 > news >正文

使用QueryBuilders、NativeSearchQuery实现复杂查询

使用QueryBuilders、NativeSearchQuery实现复杂查询

本文继续前面文章《ElasticSearch系列(二)springboot中集成使用ElasticSearch的Demo》,在前文中,我们介绍了使用springdata做一些简单查询,但是要实现一些高级的组合等查询,还是需要使用ES的一些原生方法。

本文介绍一些高级查询用法。需要看环境搭建的,先直接看前文。

数据准备:
es中事先插入了20多条数据,用于测试,然后title和content使用了ik_smart分词:

一、ElasticsearchRestTemplate

ElasticsearchRestTemplate是Spring封装ES客户端的一些原生api模板,方便实现一些查询,和ElasticsearchTemplate一样,但是目前spring推荐使用前者,是一种更高级的REST风格api。

废话不多说,先上一个demo,

@RunWith(SpringRunner.class)
@SpringBootTest
public class EsArticleControllerTest {@Autowiredprivate ElasticsearchRestTemplate elasticsearchRestTemplate;@Testpublic void test1() {NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()//查询条件.withQuery(QueryBuilders.queryStringQuery("浦东开发开放").defaultField("title"))//分页.withPageable(PageRequest.of(0, 5))//排序.withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC))//高亮字段显示.withHighlightFields(new HighlightBuilder.Field("浦东")).build();List<ArticleEntity> articleEntities = elasticsearchRestTemplate.queryForList(nativeSearchQuery, ArticleEntity.class);articleEntities.forEach(item -> System.out.println(item.toString()));}
}

这个方法是根据指定的title模糊查询一个列表,其中用到了几个关键类,说明一下:

elasticsearchRestTemplate.queryForList是查询一个列表,用的就是ElasticsearchRestTemplate的一个对象实例;
NativeSearchQuery :是springdata中的查询条件;
NativeSearchQueryBuilder :用于建造一个NativeSearchQuery查询对象;
QueryBuilders :设置查询条件,是ES中的类;
SortBuilders :设置排序条件;
HighlightBuilder :设置高亮显示;

下面分类具体介绍下。

二、NativeSearchQuery

这是一个原生的查询条件类,用来和ES的一些原生查询方法进行搭配,实现一些比较复杂的查询。

下面是NativeSearchQuery的一些内部属性,基本上都是ES的一些内部对象:

//查询条件,查询的时候,会考虑关键词的匹配度,并按照分值进行排序
private QueryBuilder query;
//查询条件,查询的时候,不考虑匹配程度以及排序这些事情
private QueryBuilder filter;
//排序条件的builder
private List<SortBuilder> sorts;
private final List<ScriptField> scriptFields = new ArrayList<>();
private CollapseBuilder collapseBuilder;
private List<FacetRequest> facets;
private List<AbstractAggregationBuilder> aggregations;
//高亮显示的builder
private HighlightBuilder highlightBuilder;
private HighlightBuilder.Field[] highlightFields;
private List<IndexBoost> indicesBoost;

上述属性的值,就像demo的写的,通过NativeSearchQueryBuilder进行构建即可,最终作为elasticsearchRestTemplate的查询条件入参。

三、QueryBuilders

QueryBuilders是ES中的查询条件构造器。下面结合一些具体的查询场景,分析其常用方法。

ES中已经有title为 “***关心浦东开发开放” 的数据;

ik_smart分词结果:

{
"tokens": [
{
"token": "***",
"start_offset": 3,
"end_offset": 6,
"type": "CN_WORD",
"position": 1
},
{
"token": "关心",
"start_offset": 6,
"end_offset": 8,
"type": "CN_WORD",
"position": 2
},
{
"token": "浦东",
"start_offset": 8,
"end_offset": 10,
"type": "CN_WORD",
"position": 3
},
{
"token": "开发",
"start_offset": 10,
"end_offset": 12,
"type": "CN_WORD",
"position": 4
},
{
"token": "开放",
"start_offset": 12,
"end_offset": 14,
"type": "CN_WORD",
"position": 5
}
]
}
3.1精确查询

精确,指的是查询关键字(或者关键字分词后),必须与目标分词结果完全匹配。

1.指定字符串作为关键词查询,关键词支持分词

//查询title字段中,包含 ”开发”、“开放" 这个字符串的document;相当于把"浦东开发开放"分词了,再查询;
QueryBuilders.queryStringQuery(“开发开放”).defaultField(“title”);
//不指定feild,查询范围为所有feild
QueryBuilders.queryStringQuery(“青春”);
//指定多个feild
QueryBuilders.queryStringQuery(“青春”).field(“title”).field(“content”);

2.以关键字“开发开放”,关键字不支持分词

QueryBuilders.termQuery(“title”, “开发开放”)
QueryBuilders.termsQuery(“fieldName”, “fieldlValue1”,“fieldlValue2…”)

3.以关键字“开发开放”,关键字支持分词

QueryBuilders.matchQuery(“title”, “开发开放”)
QueryBuilders.multiMatchQuery(“fieldlValue”, “fieldName1”, “fieldName2”, “fieldName3”)

3.2 模糊查询

模糊,是指查询关键字与目标关键字可以模糊匹配。

1.左右模糊查询,其中fuzziness的参数作用是在查询时,es动态的将查询关键词前后增加或者删除一个词,然后进行匹配

QueryBuilders.fuzzyQuery(“title”, “开发开放”).fuzziness(Fuzziness.ONE)

2.前缀查询,查询title中以“开发开放”为前缀的document;

QueryBuilders.prefixQuery(“title”, “开发开放”)

3.通配符查询,支持*和?,?表示单个字符;注意不建议将通配符作为前缀,否则导致查询很慢

QueryBuilders.wildcardQuery(“title”, “开*放”)
QueryBuilders.wildcardQuery(“title”, “开?放”)

注意,
在分词的情况下,针对fuzzyQuery、prefixQuery、wildcardQuery不支持分词查询,即使有这种doucment数据,也不一定能查出来,因为分词后,不一定有“开发开放”这个词;

查询总结:

开发开放 放 开
queryStringQuery 目标中含有开发、开放、开发开放的 无 无
matchQuery 同queryStringQuery 无 无
termQuery 无结果,因为它不支持分词 无 无
prefixQuery 无结果,因为它不支持分词 无 有,目标分词中以”开“开头的
fuzzyQuery 无结果,但是与fuzziness参数有关系 无 无
wildcardQuery 开发开放无结果 开,有 放*,无

3.3 范围查询

//闭区间查询
QueryBuilders.rangeQuery(“fieldName”).from(“fieldValue1”).to(“fieldValue2”);
//开区间查询,默认是true,也就是包含
QueryBuilders.rangeQuery(“fieldName”).from(“fieldValue1”).to(“fieldValue2”).includeUpper(false).includeLower(false);
//大于
QueryBuilders.rangeQuery(“fieldName”).gt(“fieldValue”);
//大于等于
QueryBuilders.rangeQuery(“fieldName”).gte(“fieldValue”);
//小于
QueryBuilders.rangeQuery(“fieldName”).lt(“fieldValue”);
//小于等于
QueryBuilders.rangeQuery(“fieldName”).lte(“fieldValue”);

3.4 多个关键字组合查询boolQuery()
QueryBuilders.boolQuery()
QueryBuilders.boolQuery().must();//文档必须完全匹配条件,相当于and
QueryBuilders.boolQuery().mustNot();//文档必须不匹配条件,相当于not
QueryBuilders.boolQuery().should();//至少满足一个条件,这个文档就符合should,相当于or

具体demo如下:

public void testBoolQuery() {
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.boolQuery()
.should(QueryBuilders.termQuery(“title”, “开发”))
.should(QueryBuilders.termQuery(“title”, “青春”))
.mustNot(QueryBuilders.termQuery(“title”, “潮头”))
)
.withSort(SortBuilders.fieldSort(“id”).order(SortOrder.DESC))
.withPageable(PageRequest.of(0, 50))
.build();
List articleEntities = elasticsearchRestTemplate.queryForList(nativeSearchQuery, ArticleEntity.class);
articleEntities.forEach(item -> System.out.println(item.toString()));
}

以上是查询title分词中,包含“开发”或者“青春”,但不能包含“潮头”的document;
也可以多个must组合。

四、SortBuilders排序

上述demo中,我们使用了排序条件:

//按照id字段降序
.withSort(SortBuilders.fieldSort(“id”).order(SortOrder.DESC))
1
2
注意排序时,有个坑,就是在以id排序时,比如降序,结果可能并不是我们想要的。因为根据id排序,es实际上会根据_id进行排序,但是_id是string类型的,排序后的结果会与整型不一致。

建议:
在创建es的索引mapping时,将es的id和业务的id分开,比如业务id叫做myId:

@Id
@Field(type = FieldType.Long, store = true)
private Long myId;@Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
private String title;@Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
private String content;

这样,后续排序可以使用myId进行排序。

五、分页

使用如下方式分页:

@Test
public void testPage() {
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("title", "青春"))
.withSort(SortBuilders.fieldSort("myId").order(SortOrder.DESC))
.withPageable(PageRequest.of(0, 50))
.build();
AggregatedPage<ArticleEntity> page = elasticsearchRestTemplate.queryForPage(nativeSearchQuery, ArticleEntity.class);
List<ArticleEntity> articleEntities = page.getContent();
articleEntities.forEach(item -> System.out.println(item.toString()));
}

注意,如果不指定分页参数,es默认只显示10条。

六、高亮显示
查询title字段中的关键字,并高亮显示:

@Test
public void test() {String preTag = "<font color='#dd4b39'>";String postTag = "</font>";NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchQuery("title", "开发")).withPageable(PageRequest.of(0, 50)).withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC)).withHighlightFields(new HighlightBuilder.Field("title").preTags(preTag).postTags(postTag)).build();AggregatedPage<ArticleEntity> page = elasticsearchRestTemplate.queryForPage(nativeSearchQuery, ArticleEntity.class,new SearchResultMapper() {@Overridepublic <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {List<ArticleEntity> chunk = new ArrayList<>();for (SearchHit searchHit : response.getHits()) {if (response.getHits().getHits().length <= 0) {return null;}ArticleEntity article = new ArticleEntity();article.setMyId(Long.valueOf(searchHit.getSourceAsMap().get("id").toString()));article.setContent(searchHit.getSourceAsMap().get("content").toString());HighlightField title = searchHit.getHighlightFields().get("title");if (title != null) {article.setTitle(title.fragments()[0].toString());}chunk.add(article);}if (chunk.size() > 0) {return new AggregatedPageImpl<>((List<T>) chunk);}return null;}@Overridepublic <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {return null;}});List<ArticleEntity> articleEntities = page.getContent();
articleEntities.forEach(item -> System.out.println(item.toString()));
}

结果:

title=勇立潮头——***关心浦东开发开放40, content=外交部:望

相关文章:

使用QueryBuilders、NativeSearchQuery实现复杂查询

使用QueryBuilders、NativeSearchQuery实现复杂查询 本文继续前面文章《ElasticSearch系列&#xff08;二&#xff09;springboot中集成使用ElasticSearch的Demo》&#xff0c;在前文中&#xff0c;我们介绍了使用springdata做一些简单查询&#xff0c;但是要实现一些高级的组…...

taobao.open.account.update( Open Account数据更新 )

&#xffe5;开放平台免费API不需用户授权 Open Account数据更新 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 响应参数 点击获取key和secret 请求示例 TaobaoClient client new DefaultTaobaoClient(url, appkey, sec…...

PT100铂电阻温度传感器

PT100温度传感器又叫做铂热电阻。     热电阻是中低温区&#xfe61;常用的一种温度检测器。它的主要特点是测量精度高&#xff0c;性能稳定。其中铂热电阻的测量精确度是&#xfe61;高的&#xff0c;它不仅广泛应用于工业测温&#xff0c;而且被制成标准的基准仪。金属热…...

蓝桥杯-本质上升序列

没有白走的路&#xff0c;每一步都算数&#x1f388;&#x1f388;&#x1f388; 题目描述&#xff1a; 小蓝特别喜欢单调递增的事物 在一个字符串中如果取出若干个字符&#xff0c;按照在原来字符串中的顺序排列在一起&#xff0c;组成的新的字符串如果是单调递增的&#xf…...

synchronized锁重入验证

文章目录synchronized锁重入验证1. 可重入锁2. synchronized锁重入2.1 本类同步方法内部调用本类其它同步方法2.2 子类同步方法内部调用父类的同步方法2.3 A类的同步方法内部调用B类的同步方法3. synchronized修饰方法写法synchronized锁重入验证 1. 可重入锁 可重入锁&#…...

超简单的计数排序!!

假设给定混乱数据为&#xff1a;3&#xff0c;0&#xff0c;1&#xff0c;3&#xff0c;6&#xff0c;5&#xff0c;4&#xff0c;2&#xff0c;1&#xff0c;9。 下面我们将通过使用计数排序的思想来完成对上面数据的排序。(先不谈负数) 计数排序 该排序的思路和它的名字一样…...

发现新大陆——原来软件开发根本不需要会编码(看我10分钟应用上线)

目录 一、前言 二、官网基础功能及搭建 三、体验过程 01、连接数据源 02、设计表单 03、流程设计 04、图表呈现 05、组织架构设置 五、效率评价 六、小结 一、前言 众所周知&#xff0c;每家公司在发展过程中都需要构建大量的内部系统&#xff0c; 如运营使用的用户…...

【Leedcode】栈和队列必备的面试题(第二期)

【Leedcode】栈和队列必备的面试题&#xff08;第二期&#xff09; 文章目录【Leedcode】栈和队列必备的面试题&#xff08;第二期&#xff09;一、题目&#xff08;用两个队列实现栈&#xff09;二、思路图解1.定义两个队列2.初始化两个队列3.往两个队列中放入数据4.两个队列出…...

Elasticsearch实战之(商品搜索API实现)

Elasticsearch实战之&#xff08;商品搜索API实现&#xff09; 1、案例介绍 某医药电商H5商城基于Elasticsearch实现商品搜索 2、案例分析 2.1、数据来源 商品库 - 平台运营维护商品库 - 供应商维护 2.2、数据同步 2.2.1、同步双写 写入 MySQL&#xff0c;直接也同步往…...

剑指 Offer 14-剪绳子

摘要 ​​​​​​剑指 Offer 14- I. 剪绳子 剑指 Offer 14- II. 剪绳子 II 343. 整数拆分 一、动态规划解析 这道题给定一个大于1的正整数n&#xff0c;要求将n 拆分成至少两个正整数的和&#xff0c;并使这些正整数的乘积最大化&#xff0c;返回最大乘积。令x是拆分出的第…...

泰克示波器|MSO64示波器的应用

泰克新一代示波器MSO64为实例来讲解时频域信号分析技术。MSO64采用全新TEK049平台&#xff0c;不仅实现了4通道同时打开时25GS/s的高采样率&#xff0c;而且实现了12-bit高垂直分辨率。同时&#xff0c;由于采用了新型低噪声前端放大ASIC—TEK061&#xff0c;大大降低了噪声水平…...

1.4 黑群晖安装:SataPortMap和DiskIdxMap两种获取方式

tinycore及安装工具下载&#xff1a;工具&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1CMLl6waOuW-Ys2gKZx7Jgg?pwdchct提取码&#xff1a;chcttinycore&#xff1a;链接&#xff1a;https://pan.baidu.com/s/19lchzLj-WDXPQu2cEcskBg?pwddcw2 提取码&#xff1a;d…...

JVM虚拟机概述(2)

3.JVM 运行时数据区 3.1.1 程序计数器&#xff08;Program Counter Register&#xff09; 是一块很小的内存空间,用来记录每个线程运行的指令位置&#xff0c;是线程私有的,每个线程都拥有一个程序计数器&#xff0c;生命周期与线程一致&#xff0c;是运行时数据区中唯一一个不…...

Intel CSME 简述

SME 算是 Intel X86 PC 上最神秘的部分了,本文根据 us-19-Hasarfaty-Behind-The-Scenes-Of-Intel-Security-And-Manageability-Engine 一文写成。讲述内容无法证伪,各位随便听听即可,了解这些能够帮助BIOS 工程师更好的理解一些操作的实现。文章基于 Intel 第八代第九代CPU(…...

复位理论基础

先收集资料&#xff0c;了解当前常用的基础理论和实现方式 复位 初始化微控制器内部电路 将所有寄存器恢复成默认值确认MCU的工作模式禁止全局中断关闭外设将IO设置为高阻输入状态等待时钟趋于稳定从固定地址取得复位向量并开始执行 造成复位的原因 有多种引起复位的因素&…...

Python基础知识——列表

列表 列表是可以存放任何数据&#xff0c;包括整型&#xff0c;浮点型&#xff0c;字符串&#xff0c;布尔型等等&#xff0c;是常用的数据类型之一。 1.列表的创建 列表也是一个可迭代对象 1. 普通形式l [1,2,3,4,5] ---整型列表l ["a","b","c&…...

如何使用工时表管理项目和非项目的资源?

对新机会做出反应的能力是企业竞争优势的关键。项目不断涌现&#xff0c;企业需要了解具体的可用性以及是否有资源来接受新事物。更进一步来说&#xff0c;企业需要知道员工将时间花在哪里。 使用 8Manage工时表解决方案&#xff0c;你将始终拥有做出正确业务决策所需的全面知…...

项目经理如何做好质量保证与标准维持?非技术项目经理如何做好质量管控?

项目经理如何做好质量保证与标准维持&#xff1f;非技术项目经理如何做好质量管控&#xff1f;01.质量保障需要重视哪些执行层面的细节02.非技术出身项目经理如何做好质量保障工作03.质量管理除了PDCA&#xff0c;还有哪些推荐的方法04.质量保证与标准维持&#xff0c;作为常态…...

[文件操作] File 类的用法和 InputStream, OutputStream 的用法

能吃是不是件幸福的事呢 文章目录前言1. 文件的相关定义2. 文件类型3. Java对文件系统的操作3.1 对文件的基础操作3.2 读文件3.3 写文件前言 从这章开始,我们就开始学文件操作相关的知识了~ 1. 文件的相关定义 1.文件的定义可以从狭义和广义两个方面解释. 狭义: 指硬盘上的文…...

索莫菲模型的一些理解 Smomerfeld Model

如何解释传统热容算出来的数值与量子模型下的区别&#xff1f; 因为只有费米能附近的电子才能够进行移动&#xff0c;这个是问题的差别所在 我们下面就来介绍如何求费米能&#xff08;费米能的计算&#xff09; 既然费米能附近的电子很重要&#xff0c;那么附近的电子有多少很…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...