自定义mongodb查找语言解析器

    技术2023-07-29  125

    常规的mongodb的查找操作如下所示。本文提供一种自定义解析器的思路,自行定义mongodb的树形结构进行查找。

    db.col.find( { $or: [ {key1: value1}, {key2: value2} ] } )

    数据库中有如下数据

    当你想要找一个叫做小C,且他的老板是sdsd的时候

    是不是已经有点想吐了,老板是sdsd或者是qwer呢

    MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

    但是查找语句写起来真的很崩溃啊喂。。

    于是我脑洞大开,我们能不能自己写一套语法便于我们查找呢,如果我能够提供像如下这种查找语句,是不是看起来容易理解多了

    ( name=小C && ( owner=sdsd || owner=qwer ) )

    是不是一下子就清爽了许多

    基于此,我想到了用栈来操作,受启发于中缀表达式 代码实现如下 当然是你们最喜欢的爪洼

    private static Map Parser(String string){ // String string="(name=张三 && (age=17 || age=18 || age=20) && sex=男)"; Stack<Map> stack=new Stack(); //stack中存放map Stack operateStack=new Stack(); //operateStack记录运算符以及优先级 Stack tempOperator=new Stack(); string.split("="); for(int i=0;i<string.length();i++) { switch (string.charAt(i)){ case '&': operateStack.push("$and"); i++; //跳过第二个& break; case '|': operateStack.push("$or"); i++; //跳过第二个| break; case '(': operateStack.push("("); break; case '=': //把 name=张三 变成一个map放入栈stack中 HashMap map=new HashMap(); //构造Map对象,入栈 //这个等于号前 到 第一个 特殊符号后的 全都是key值 int k=i; while(k>=0){ //不为特殊符号 && || ( k--; if (string.charAt(k)=='(' || string.charAt(k)=='&' || string.charAt(k)=='|'){ break; } } String key=string.substring(k+1,i); //key为 k到i之间的字符串了 k=i; while(k<string.length()){ //同理。从k往后 到第一个特殊字符之间,都是value k++; if (string.charAt(k)==')' || string.charAt(k)=='&' || string.charAt(k)=='|'){ break; } } String value=string.substring(i+1,k); map.put(key,value); stack.push(map); break; case ')': //此刻出栈 完成拼接 HashMap map1=new HashMap(); ArrayList list=new ArrayList(); // stack中取两个操作数,operaterStack中取一个运算符,拼接成$or/$and:[xx,xx],再压入栈中 String operator= (String) operateStack.pop(); if ("$or".equals(operator)) { //往前找到第一个左括号,记录经过的operator个数,这些元素全都是or关系 tempOperator.push("$or"); //认为括号内运算符都是平级的 String Nextoperator= (String) operateStack.pop(); int j=1; while(!Nextoperator.equals("(")){ j++; Nextoperator= (String) operateStack.pop(); } //说明这边有几个or 则从stack中运算几次 for(int times=0;times<=j;times++){ list.add(stack.pop()); } map1.put("$or",list); stack.push(map1); break; } if("$and".equals(operator)){ tempOperator.push("$and"); //认为括号内运算符都是平级的 String Nextoperator= (String) operateStack.pop(); int j=1; while(!Nextoperator.equals("(")){ j++; Nextoperator= (String) operateStack.pop(); } //说明这边有几个and 则从stack中运算几次 for(int times=0;times<=j;times++){ list.add(stack.pop()); } map1.put("$and",list); stack.push(map1); break; } } } return stack.pop(); }

    最后返回这样的格式

    Processed: 0.010, SQL: 10