es8中解析字符串中的"与"、"或"、"括号"拼装查询DSL
依赖
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch'
implementation 'co.elastic.clients:elasticsearch-java:8.11.0'
implementation 'com.fasterxml.jackson.core:jackson-databind'
compileOnly("org.projectlombok:lombok:1.18.30")
annotationProcessor("org.projectlombok:lombok:1.18.30")
testCompileOnly("org.projectlombok:lombok:1.18.30")
testAnnotationProcessor("org.projectlombok:lombok:1.18.30")
package cn.golaxy.lqtest.es;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import java.util.Stack;
public class ESQueryParserUtil {
public static SearchRequest parseQuery(String query) {
Stack<Character> operators = new Stack<>();
Stack<Query> 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();
Query right = operands.pop();
Query 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--;
operands.push(Query.of(q -> q.multiMatch(m -> m.fields("name").query(sb.toString().trim()))));
}
}
while (!operators.isEmpty()) {
char operator = operators.pop();
Query right = operands.pop();
Query left = operands.pop();
operands.push(applyOperator(left, right, operator));
}
return SearchRequest.of(sr -> sr.query(operands.pop()));
}
private static Query applyOperator(Query left, Query right, char operator) {
if (operator == '&') {
return Query.of(q -> q.bool(b -> b.must(left).must(right)));
} else if (operator == '|') {
return Query.of(q -> q.bool(b -> b.should(left).should(right)));
}
return null;
}
public static void main(String[] args) {
String query = "(河北&石家庄)|打架&新闻";
SearchRequest searchRequest = parseQuery(query);
System.out.println(searchRequest);
}
}
生成查询json
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"multi_match": {
"fields": [
"name"
],
"query": "河北"
}
},
{
"multi_match": {
"fields": [
"name"
],
"query": "石家庄"
}
}
]
}
},
{
"bool": {
"must": [
{
"multi_match": {
"fields": [
"name"
],
"query": "打架"
}
},
{
"multi_match": {
"fields": [
"name"
],
"query": "新闻"
}
}
]
}
}
]
}
}
}