查询表达式转变为elasticsearch查询语句,
查询表达式转变为elasticsearch查询语句
查询表达式:(a=1 | (b<2 | c>3 &f>6)) & (d=4 | e<5) | m >9 注意:带括号,且为多层嵌套;且不考虑&|优先级
思路:
1.切割查询表达式,使成为含有表达式,左右括号,关系& | 的 list 集合
2.遍历 list 集合。关系&|符号入符号栈;左括号、表达式入bool栈。遇到右括号时,则逆序遍历bool栈,并把遍历到的元素放入临时list中,直到遇到左括号为止。然后出栈,并处理这个临时list,并把返回的结果继续压入bool栈。循环处理,直到list无元素。
3.处理临时list。
3.1若只有一个元素,则变为DSL语句后,符号出栈;
3.2若为两个元素,则用符号栈的第一个元素,拼接为bool语句,符号出栈(只出一次);
3.3若为多个元素,则每个元素拼接为bool语句时,用栈中第一个元素,每个元素用完后符号栈出栈。最后那个元素无符号,则用最后一个出栈符号。
总结:
1.其实也不算非常复杂,但处理这个问题确实花费了很长时间。关键是基础薄弱,思路不清。一开始自己也没想好怎么做,就乱写。自己都没想好乱写的逻辑还奢望计算机能理解并正确运行。真是惭愧。最后自己思路清晰了,还真得就正确了。
2.对栈理解不深刻,用法也不熟悉。需要加强。
3.对经典问题算术表达式的处理不理解。需要熟悉。
4.写的看的代码太少。何谓见多识广,游刃有余?
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
public class Test4 {
public static void main(String[] args) {
String s = "(a=1 | (b<2 | c>3 &f>6)) & (d=4 | e<5) | m >9";// 分割成对象,如果遇到左括号或者是|开始分割
//s = "(a=1 | (b<2 | c>3 &f>6)) & (d=4 | e<5) & m >9";//
//s = "(a=1 | (b<2 | c>3 &f>6 | e^3) | (d=4 & e<5) & m >9)";//
//s = "a=1 | (b<2 | c>3 &f>6 | e^3) | (d=4 | e<5) & m >9";//
//s = "a=1 & (b<2 | c>3 &f>6) | ((d=4 & e<5) | m >9)";//
List list = getSplit(s);
BoolQueryBuilder bool = doBra(list);
System.out.println(bool.toString());
}
private static BoolQueryBuilder doBra(List listO) {
LinkedList<String> opraStack = new LinkedList<String>();
LinkedList boolStack = new LinkedList();
Object obj;
String s;
List list;
for (int i = 0; i < listO.size(); i++) {
obj = listO.get(i);
if (obj instanceof String) {
s = (String) obj;
if (s.equals("&") || s.equals("|")) {// 符号入栈
opraStack.push(s);
} else if (s.equals(")")) {// 如果碰到右括号
int n = 0;
list = new ArrayList<String>();
int f = 0;
for (int j = 0; j < boolStack.size(); j++) {// 循环以前的栈,直到左括号为止,并把未遇到左括号之前的都加入一个list中。
Object obj2 = boolStack.get(j);
if (obj2 instanceof String) {
if (obj2.toString().equals("(")) {
boolStack.pop();
break;
}
}
n++;
list.add(obj2);
}
for (int m = 0; m < n; m++) {// 清理栈
boolStack.pop();
}
boolStack.push(doBool(list, opraStack));// 运算后把左括号的内容加入到bool栈中
} else {
boolStack.push(obj);
}
} else {
boolStack.push(obj);
}
}
BoolQueryBuilder bool3 = doBool(boolStack, opraStack);
return bool3;
}
private static BoolQueryBuilder doBool(List list,
LinkedList<String> opraStack) {
BoolQueryBuilder bool = QueryBuilders.boolQuery();
String temp = null;
int n = 1;
boolean flag = false;
for (int i = 0; i < list.size(); i++) {
Object obj = list.get(i);
if(list.size() == 1 || list.size()==2){
if (obj instanceof Expression)
obj = doCon((Expression) obj);
if(opraStack.size()==0)
return (BoolQueryBuilder) obj;
bool = doRela(bool, (QueryBuilder) obj,
opraStack.getFirst());
if (i == 1)
opraStack.pop();
} else {
if(opraStack.size()==0){
flag = true;
opraStack.push(temp);
}
if (obj instanceof Expression) {
bool = doRela(bool, doCon((Expression) obj),opraStack.getFirst());
} else if (obj instanceof BoolQueryBuilder) {
bool = doRela(bool, (BoolQueryBuilder) obj,opraStack.getFirst());
temp = opraStack.getFirst();
}
if (n < list.size()) {
opraStack.pop();
n++;
}
}
}
if(flag)
opraStack.pop();
return bool;
}
private static QueryBuilder doCon(Expression exp) {
QueryBuilder qb = null;
String field = exp.getValueA();
String value = exp.getValueB();
String con = exp.getCal();
if ("=".equals(con))
qb = QueryBuilders.termQuery(field, value);
else if (">".equals(con))
qb = QueryBuilders.rangeQuery(field).gt(value);
else if ("<".equals(con))
qb = QueryBuilders.rangeQuery(field).lt(value);
else if ("^".equals(con))//代替不等于
qb = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery(field, value));
return qb;
}
private static BoolQueryBuilder doRela(BoolQueryBuilder bool,
QueryBuilder subBool, String opra) {
if ("&".equals(opra)) {
bool.must(subBool);
} else if ("|".equals(opra)) {
bool.should(subBool);
}
return bool;
}
private static List getSplit(String s) {
String[] ss = s.replace(" ", "").split("");
List list = new ArrayList();
List<String> listExp = new ArrayList<String>();
for (int i = 1; i < ss.length; i++) {
if (ss[i].equals("&") || (ss[i]).equals("|")) {
if (listExp.size() > 0) {
doList(list, listExp);
}
list.add(ss[i]);
} else if (ss[i].equals(")") || ss[i].equals("(")) {//
if (ss[i].equals(")") && listExp.size() > 0) {
doList(list, listExp);
}
list.add(ss[i]);
} else {
listExp.add(ss[i]);
}
}
if (listExp.size() > 0) {
doList(list, listExp);
}
return list;
}
private static void doList(List list, List<String> listExp) {
list.add(new Expression(listExp.get(0), listExp.get(2), listExp.get(1)));
listExp.clear();
}
}
表达式实体类:
public class Expression {
String valueA;
String valueB;
String cal;
public String getValueA() {
return valueA;
}
public void setValueA(String valueA) {
this.valueA = valueA;
}
public String getValueB() {
return valueB;
}
public void setValueB(String valueB) {
this.valueB = valueB;
}
public String getCal() {
return cal;
}
public void setCal(String cal) {
this.cal = cal;
}
public Expression() {
super();
}
public Expression(String valueA, String valueB, String cal) {
super();
this.valueA = valueA;
this.valueB = valueB;
this.cal = cal;
}
}
本站文章为和通数据库网友分享或者投稿,欢迎任何形式的转载,但请务必注明出处.
同时文章内容如有侵犯了您的权益,请联系QQ:970679559,我们会在尽快处理。