IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> sql select 语句 转 Json -> 正文阅读

[大数据]sql select 语句 转 Json

最近有个Es查询的需求,用户在前端输入sql语句直接拼条件,然后后台去查询。

因为es本身带有类sql查询,刚开始打算用sql查的,但是分页的limit只有一个查询条数,没有from和size,比如es可以通过类sql 的 limit 1000 一次查出来1000条数据,但是没法通过limit 900,100查出来第900到1000的数据,想实现就得先limit 1000再去截取后100条,没办法了,只能解析sql再去拼接条件了。这块的解析实现需要感谢以下两篇贴子,

灵感来源

https://elasticsearch.cn/article/114

用二叉树简直是神设计,当时为了最终结构困扰了我半天
在这里插入图片描述

https://blog.csdn.net/qzshiyongjie123/article/details/54341472

这篇关于具体代码实现讲的挺详细的,唯一的缺点是代码不全,我也是在这篇的基础上修改来的

代码实现

实现方法

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * @author fjl
 * @date 2022/5/10
 */
public class ParseSqlUtil {

    public static void main(String[] args) {

        //String sql = "( income >= 10000 or income < 100 and gender = '女' ) or monent = 10 or name = '张三' and id = 1 ";
        //String sql = "( ( income >= 10000 or income < 100 ) and ( gender = '女' or monent = 10 ) ) or ( name = '张三' ) and id = 1 ";
        String sql = "( income < 100 and gender = '女' ) or monent = 10 ";
        try {
            TreeNode brake = paraseSqlTree(sql);
        }catch (Exception e){
            System.out.println("Sql语法有误,请检查后重试");
        }
    }

    public static TreeNode paraseSqlTree(String sql) {
        sql = sql.trim();
        TreeNode tempNode = new TreeNode();
        if (sql.startsWith("(")) {
            //构建括号里的数据
            TreeNode braketsNode = subBrackets(sql);
            if (braketsNode != null) {
                if (braketsNode.right != null && !(braketsNode.right.value.equals(""))) {
                    // 左边树
                    tempNode.left = paraseSqlTree(braketsNode.left.value.toString());
                    // 关系符
                    tempNode.value = braketsNode.value;
                    // 右边树
                    tempNode.right = paraseSqlTree(braketsNode.right.value.toString());
                } else {
                    // 右边的是空的,就只处理左边的
                    tempNode = paraseSqlTree(braketsNode.left.value.toString());
                }
                return tempNode;
            }
        } else {
            return dealGoOn(sql.split(" "), 0);
        }
        return null;
    }

    private static TreeNode subBrackets(String sql) {
        TreeNode node = new TreeNode();
        Queue<String> queue = new ArrayDeque<String>();
        for (int i = 0; i < sql.length(); i++) {
            char temchar = sql.charAt(i);
            if (temchar == '(') {
                queue.add("(");
            }
            if (temchar == ')') {
                queue.poll();
                if (queue.size() == 0) {
                    // 拆解数据
                    node.left = new TreeNode(sql.substring(1, i - 1));
                    node.right = new TreeNode(sql.substring(i + 1, sql.length()).trim());
                    if (null != node.right && !(node.right.value.equals(""))) {
                        String rightStr = node.right.value.toString();
                        boolean isAnd = rightStr.substring(0, 3).equals("and") ? true : false;
                        String value = "";
                        String right = "";
                        if (isAnd) {
                            value = "and";
                            right = rightStr.substring(4, rightStr.length()).trim();
                        } else {
                            value = "or";
                            right = rightStr.substring(3, rightStr.length()).trim();
                        }
                        node.right = new TreeNode(right);
                        node.value = new TreeNode(value);
                    }
                    return node;
                }
            }
        }
        // 括号分解有问题,sql语法错误
        return node;
    }

    private static TreeNode dealGoOn(String[] stre, int j) {
        TreeNode tempNode = new TreeNode();
        for (int i = j; i < stre.length; i++) {
            String temstr = stre[i];
            if (temstr.matches("(and)|(or)")) {
                // 先组装前面的条件树
                TreeNode curNode = getNode(stre, i - 3, i - 1, i - 2);
                TreeNode parentNode = new TreeNode();
                parentNode.value = temstr;
                if (tempNode != null) {
                    parentNode.left = curNode;
                    // 继续遍历组装
                    parentNode.right = dealGoOn(stre, i + 1);
                }
                return parentNode;
            } else {
                if (i + 2 == stre.length) {
                    // 循环完了,组装后面的树
                    TreeNode curNode = getNode(stre, i - 1, i + 1, i);
                    return curNode;
                }
            }
        }
        return null;
    }

    private static TreeNode getNode(String[] stre, int leftIndex, int rightIndex, int valueIndex) {
        // 去除 包中文的 '' in 的 ()
        String rightV= (stre[rightIndex].startsWith("'") || stre[rightIndex].startsWith("("))?stre[rightIndex].substring(1,stre[rightIndex].length()-1):stre[rightIndex];

        TreeNode leftNode = new TreeNode(stre[leftIndex]);
        TreeNode rightNode = new TreeNode(rightV);
        TreeNode curNode = new TreeNode();
        curNode.setLeft(leftNode);
        curNode.setRight(rightNode);
        curNode.setValue(new TreeNode(stre[valueIndex]));
        return curNode;
    }
}

TreeNode实体类

import lombok.Data;

/**
 * @author fjl
 * @date 2022/5/9
 */
@Data
public class TreeNode {
    TreeNode left;
    TreeNode right;
    Object value;
    public TreeNode() {
    }
    public TreeNode(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "TreeNode{" +
                "left=" + left +
                ", right=" + right +
                ", value=" + value +
                '}';
    }
}

最终结构

{
    "left": {
        "left": {
            "left": {
                "left": null,
                "right": null,
                "value": "income"
            },
            "right": {
                "left": null,
                "right": null,
                "value": "100"
            },
            "value": {
                "left": null,
                "right": null,
                "value": "<"
            }
        },
        "right": {
            "left": {
                "left": null,
                "right": null,
                "value": "gender"
            },
            "right": {
                "left": null,
                "right": null,
                "value": "女"
            },
            "value": {
                "left": null,
                "right": null,
                "value": "="
            }
        },
        "value": "and"
    },
    "right": {
        "left": {
            "left": null,
            "right": null,
            "value": "monent"
        },
        "right": {
            "left": null,
            "right": null,
            "value": "10"
        },
        "value": {
            "left": null,
            "right": null,
            "value": "="
        }
    },
    "value": {
        "left": null,
        "right": null,
        "value": "or"
    }
}

需要注意的是关系符合字段之间只能有一个空格,多了的话会出问题,这个现阶段得让前端控制一下。
转成Json后,在后台就可以用QueryBuilders去遍历组装查询条件了

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:30:44  更:2022-05-11 16:31:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:00:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码