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

将字符串 “()“ ““ “|“ 条件组成的复杂表达式转换为ES查询语句

应用场景

"()" "&" "|"  这几个条件对于我们来说并不陌生, 其表达的逻辑非常明了, 又能通过很少的字符表达很复杂的嵌套关系, 在一些复杂的查询中会经常用到, 因此我最近也遇到了类似的问题,一开始觉得这类的工具应该挺常见的, 结果搜了半天没有找到合适的,因此决定自己写一个

简介

此工具的复杂之处在于我们并不确定操作系统的人员会输入怎样的表达式,格式并不是固定的因此可能会书写出较为复杂的逻辑. 也有可能只嵌套一层就结束了,所以我们的代码一定要考虑的通用

此处我简单说一下它的原理, 主要是用到了一个java中栈的概念: 这个工具通过解析输入的逻辑查询字符串,使用栈来管理运算符和操作数,构建出对应的查询树,然后将其转换为Elasticsearch的多字段(如标题、摘要、正文)的搜索查询,实现复杂的逻辑查询条件的自动解析和执行。

以下代码全部都加了注释, 应该是不难理解的 

代码

package com.sinosoft.springbootplus.lft.business.dispatch.publicopinion.util;import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;import java.util.Stack;/*** 构建ES复杂查询条件,包含括号、逻辑运算符和操作符** @author zzt* @date 2024-05-28*/
public class ESQueryParserUtil {/*** 解析输入字符串并将其转换为Elasticsearch的QueryBuilder** @param query 输入的查询字符串* @return Elasticsearch的QueryBuilder*/public static SearchSourceBuilder parseQuery(String query) {// 存储运算符的栈Stack<Character> operators = new Stack<>();// 存储操作数的栈Stack<QueryBuilder> operands = new Stack<>();for (int i = 0; i < query.length(); i++) {char ch = query.charAt(i);if (ch == '(' || ch == '&' || ch == '|') {// 遇到左括号或者运算符时,压入运算符栈operators.push(ch);} else if (ch == ')') {// 遇到右括号时,弹出运算符栈中的运算符并进行计算直到遇到左括号while (!operators.isEmpty() && operators.peek() != '(') {char operator = operators.pop();QueryBuilder right = operands.pop();QueryBuilder left = operands.pop();operands.push(applyOperator(left, right, operator));}operators.pop(); // 弹出左括号} else if (Character.isLetterOrDigit(ch) || ch == ' ') {// 遇到字母、数字、空格或者“地区”时,构建查询字符串StringBuilder sb = new StringBuilder();while (i < query.length() && (Character.isLetterOrDigit(query.charAt(i)) || query.charAt(i) == ' ')) {sb.append(query.charAt(i));i++;}i--; // 回退一个字符,因为外层for循环会前进一个字符operands.push(QueryBuilders.multiMatchQuery(sb.toString().trim(), "title", "sysAbstract", "content"));//此处是我的ES中要模糊搜索的三个字段, 这里请自行更改}}// 处理剩余的运算符while (!operators.isEmpty()) {char operator = operators.pop();QueryBuilder right = operands.pop();QueryBuilder left = operands.pop();operands.push(applyOperator(left, right, operator));}return new SearchSourceBuilder().query(operands.pop());}/*** 根据运算符将两个操作数组合成一个QueryBuilder** @param left     左操作数* @param right    右操作数* @param operator 运算符* @return 组合后的QueryBuilder*/private static QueryBuilder applyOperator(QueryBuilder left, QueryBuilder right, char operator) {BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();if (operator == '&') {boolQuery.must(left).must(right);} else if (operator == '|') {boolQuery.should(left).should(right);}return boolQuery;}public static void main(String[] args) {String query = "((北京|天津|(河北&石家庄))&(打架|辱骂|违法))&(中国)";SearchSourceBuilder searchSourceBuilder = parseQuery(query);System.out.println(searchSourceBuilder);}
}

 生成的查询条件

由于我写的这个算是稍微复杂一点的嵌套,生成的查询条件还是挺长的, 感兴趣的可以试一下

{"query": {"bool": {"must": [{"bool": {"must": [{"bool": {"should": [{"multi_match": {"query": "北京","fields": ["content^1.0","sysAbstract^1.0","title^1.0"],"type": "best_fields","operator": "OR","slop": 0,"prefix_length": 0,"max_expansions": 50,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"fuzzy_transpositions": true,"boost": 1.0}},{"bool": {"should": [{"multi_match": {"query": "天津","fields": ["content^1.0","sysAbstract^1.0","title^1.0"],"type": "best_fields","operator": "OR","slop": 0,"prefix_length": 0,"max_expansions": 50,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"fuzzy_transpositions": true,"boost": 1.0}},{"bool": {"must": [{"multi_match": {"query": "河北","fields": ["content^1.0","sysAbstract^1.0","title^1.0"],"type": "best_fields","operator": "OR","slop": 0,"prefix_length": 0,"max_expansions": 50,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"fuzzy_transpositions": true,"boost": 1.0}},{"multi_match": {"query": "石家庄","fields": ["content^1.0","sysAbstract^1.0","title^1.0"],"type": "best_fields","operator": "OR","slop": 0,"prefix_length": 0,"max_expansions": 50,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"fuzzy_transpositions": true,"boost": 1.0}}],"adjust_pure_negative": true,"boost": 1.0}}],"adjust_pure_negative": true,"boost": 1.0}}],"adjust_pure_negative": true,"boost": 1.0}},{"bool": {"should": [{"multi_match": {"query": "打架","fields": ["content^1.0","sysAbstract^1.0","title^1.0"],"type": "best_fields","operator": "OR","slop": 0,"prefix_length": 0,"max_expansions": 50,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"fuzzy_transpositions": true,"boost": 1.0}},{"bool": {"should": [{"multi_match": {"query": "辱骂","fields": ["content^1.0","sysAbstract^1.0","title^1.0"],"type": "best_fields","operator": "OR","slop": 0,"prefix_length": 0,"max_expansions": 50,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"fuzzy_transpositions": true,"boost": 1.0}},{"multi_match": {"query": "违法","fields": ["content^1.0","sysAbstract^1.0","title^1.0"],"type": "best_fields","operator": "OR","slop": 0,"prefix_length": 0,"max_expansions": 50,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"fuzzy_transpositions": true,"boost": 1.0}}],"adjust_pure_negative": true,"boost": 1.0}}],"adjust_pure_negative": true,"boost": 1.0}}],"adjust_pure_negative": true,"boost": 1.0}},{"multi_match": {"query": "中国","fields": ["content^1.0","sysAbstract^1.0","title^1.0"],"type": "best_fields","operator": "OR","slop": 0,"prefix_length": 0,"max_expansions": 50,"zero_terms_query": "NONE","auto_generate_synonyms_phrase_query": true,"fuzzy_transpositions": true,"boost": 1.0}}],"adjust_pure_negative": true,"boost": 1.0}}
}

 

相关文章:

将字符串 “()“ ““ “|“ 条件组成的复杂表达式转换为ES查询语句

应用场景 "()" "&" "|" 这几个条件对于我们来说并不陌生, 其表达的逻辑非常明了, 又能通过很少的字符表达很复杂的嵌套关系, 在一些复杂的查询中会经常用到, 因此我最近也遇到了类似的问题,一开始觉得这类的工具应该挺常见的, 结果搜了半天…...

2024上半年软考 考试心得

考试的时候感觉选择题有点偏&#xff0c;很多概念题都不知道是什么&#xff0c;好像没怎么见过&#xff0c;什么拖库洗库&#xff0c;linux权限号不会&#xff0c;python也不确定&#xff0c;但也算顺利&#xff1b;下午题的数据库竟然没考主键外键&#xff0c;我的天哪&#x…...

【redis】set和zset常用命令

set 无序集合类型 sadd 和 smembers SADD&#xff1a;将一个或者多个元素添加到set中。注意,重复的元素无法添加到set中。 语法&#xff1a;SADD key member [member] 把集合中的元素,叫做member,就像hash类型中,叫做field类似. 返回值表示本次操作,添加成功了几个元素. 时间复…...

【面试题-006】java中的垃圾回算法有哪些?

Java中的垃圾回收&#xff08;Garbage Collection&#xff0c;简称GC&#xff09;是指自动内存管理的一种机制&#xff0c;用于回收不再使用的对象占用的内存。Java中的垃圾回收算法主要有以下几种&#xff1a; 标记-清除&#xff08;Mark-Sweep&#xff09;算法&#xff1a; …...

最小时间差

首先可以想到&#xff0c;可以计算出任意两个时间之间的差值&#xff0c;然后比较出最小的&#xff0c;不过这种蛮力方法时间复杂度是O(n^2)。而先将时间列表排序&#xff0c;再计算相邻两个时间的差值&#xff0c;就只需要计算n个差值&#xff0c;而排序阶段时间复杂度通常为O…...

动态SQL IF语句

IF语句学习 第一种写法(标准) 我们先来看以下标准写法: select * from .. <where> <if test""> and ....... <if test""> and ....... <where> 我们用了一个where标签 , 内嵌if语句 第二种写法: 这是第二种写法:不用where标…...

961题库 北航计算机 操作系统 附答案 选择题形式

有题目和答案&#xff0c;没有解析&#xff0c;不懂的题问大模型即可&#xff0c;无偿分享。 第1组 习题 计算机系统的组成包括&#xff08; &#xff09; A、程序和数据 B、处理器和内存 C、计算机硬件和计算机软件 D、处理器、存储器和外围设备 财务软件是一种&#xff…...

SylixOS 版本与 RealEvo-IDE 版本对应关系说明

SylixOS 版本与 RealEvo-IDE 版本对应关系说明 SylixOS 版本IDE 版本发布日期1.4.13.1.52017/01/171.5.23.5.12017/10/121.7.13.8.32018/06/221.8.33.9.52018/10/081.9.9-103.9.102020/01/021.11.63.10.22020/05/131.11.73.10.x2020/06/121.12.93.11.02020/09/111.12.11&#…...

linux命令:调试必备工具dmesg

在服务器上进行芯片调试时&#xff0c;我们会遇到各种各样的问题&#xff0c;很多问题与操作系统相关。此时就需要了解操作系统发生了哪些事件。 dmesg 是linux系统中用来打印或控制内核缓冲区内容的命令。这个环形缓冲区记录了系统启动以来发生的各种事件消息&#xff0c;包括…...

第三届大湾区算力大会丨暴雨开启数字未来新篇

5月30-31日&#xff0c;韶关市迎来主题为“算启新篇智创未来”的第三届粤港澳大湾区(广东)算力产业大会暨第二届中国算力网大会&#xff0c;活动由广东省人民政府主办&#xff0c;广东省政数局、韶关市人民政府共同承办。暴雨信息作为算力产业发展的重要构建者受邀赴会&#xf…...

SPWM载波调制方式-三电平杂记1

方法一&#xff1a; P2 O1 N0 方法二&#xff1a;双载波直接发波 方法三&#xff1a;负轴载波和调制波往上抬升1&#xff0c;得到使用同一个载波 在正半周在P和O切换&#xff0c;在下半轴式O和N切换...

常见攻击类型整理

文章目录 网络攻击web攻击XSS攻击存储型XSS反射型XSSDOM型XSS CSRF攻击SQL注入攻击文件上传漏洞业务逻辑漏洞越权访问水平越权垂直越权 密码找回验证码漏洞 信息泄露暴力破解远程命令执行&#xff08;RCE&#xff09;xxe注入反序列化文件包含本地文件包含&#xff08;LFI&#…...

R语言探索与分析-美国房价及其影响因素分析

一、选题背景 以多元线性回归统计模型为基础&#xff0c;用R语言对美国部分地区房价数据进行建模预测&#xff0c;进而探究提高多元回 归线性模型精度的方法。先对数据进行探索性预处理&#xff0c;随后设置虚拟变量并建模得出预测结果&#xff0c;再使用方差膨胀因子对 多重共…...

Android14 WMS-窗口添加流程(一)-Client端

窗口布局在onCreate方法中通过setContentView(R.layout.xxx)加载&#xff0c;但窗口的显示并不是在wm_on_create_called中, 而是在wm_on_resume_called后&#xff0c;也就是说应用onResume时此窗口是不可见的&#xff0c;真正可见是当此window窗口的mDrawState变化状态从NO_SUR…...

【人工智能】第二部分:ChatGPT的架构设计和训练过程

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…...

Informer

I n f o r m e r Informer Informer 摘要&#xff1a; 长序列时间序列的预测 i n f o r m e r informer informer优点&#xff1a; P r o b s p a r e Probspare Probspare自关注机制&#xff0c;在时间复杂度和内存使用方面达到 O ( N l o g N ) O(NlogN) O(NlogN),在序列依…...

12岁学什么编程机构好:深入剖析与全面指导

12岁学什么编程机构好&#xff1a;深入剖析与全面指导 在数字化时代&#xff0c;编程已成为一项必备技能。对于12岁的孩子来说&#xff0c;选择一个合适的编程机构至关重要。然而&#xff0c;市场上的编程机构众多&#xff0c;如何选择成为了一个难题。本文将从四个方面、五个…...

Day60 柱状图中最大的矩形

84 柱状图中最大的矩形 题目链接&#xff1a;84. 柱状图中最大的矩形 - 力扣&#xff08;LeetCode&#xff09; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的…...

typescript --object对象类型

ts中的object const obj new Object()Object 这里的Object是Object类型&#xff0c;而不是JavaScript内置的Object构造函数。 这里的Object是一种类型&#xff0c;而Object()构造函数表示一个值。 Object()构造函数的ts代码 interface ObjectConstructor{readonly prototyp…...

如何使用python将多个EXCEL表进行合并

在Python中&#xff0c;你可以使用pandas库来轻松地将多个Excel表格合并。以下是一个基本的步骤指南和示例代码&#xff0c;说明如何合并多个Excel文件到一个单独的DataFrame中&#xff1a; 步骤 安装pandas和openpyxl&#xff08;如果你正在处理.xlsx文件&#xff09;。导入…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践

前言&#xff1a;本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中&#xff0c;跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南&#xff0c;你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案&#xff0c;并结合内网…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...