|
@ -0,0 +1,227 @@
|
|
|
package com.yihu.iot.service.common;
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.yihu.jw.datainput.Data;
|
|
|
import com.yihu.jw.datainput.StepInfoDO;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.elasticsearch.index.query.*;
|
|
|
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
|
|
import org.elasticsearch.search.sort.FieldSortBuilder;
|
|
|
import org.elasticsearch.search.sort.SortOrder;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
|
import javax.annotation.PostConstruct;
|
|
|
import java.beans.PropertyDescriptor;
|
|
|
import java.util.*;
|
|
|
|
|
|
@Component
|
|
|
public class ElasticSearchQueryGenerator {
|
|
|
|
|
|
private static Map<String,Set<String>> fieldsMap = new HashMap<>();
|
|
|
|
|
|
@PostConstruct
|
|
|
public static void init(){
|
|
|
Set<String> fieldsSet = new HashSet<>();
|
|
|
PropertyDescriptor[] properties = BeanUtils.getPropertyDescriptors(Data.class);
|
|
|
for(PropertyDescriptor field:properties){
|
|
|
fieldsSet.add(field.getName());
|
|
|
}
|
|
|
fieldsMap.put("data",fieldsSet);
|
|
|
Set<String> fieldsSet2 = new HashSet<>();
|
|
|
PropertyDescriptor[] properties2 = BeanUtils.getPropertyDescriptors(StepInfoDO.class);
|
|
|
for(PropertyDescriptor field:properties2){
|
|
|
fieldsSet2.add(field.getName());
|
|
|
}
|
|
|
fieldsMap.put("stepInfoList",fieldsSet2);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 构造es查询参数
|
|
|
* @param jsonData
|
|
|
*
|
|
|
{
|
|
|
"filter":[{"andOr":"and|or","condition":">|=|<|>=|<=|?","field":"<filed>","value":"<value>"},<{...}>],
|
|
|
- 参数说明:andOr跟数据库的中的AND和OR相似;condition指条件匹配程度,?相当于数据库中的like;filed指检索的字段;value为检索的值
|
|
|
"page":1, - 参数格式:页码,默认1,int类型 不需要分页,传""
|
|
|
"size":10, - 参数格式:条数,默认10,int类型 不需要分页,传""
|
|
|
"sort":[
|
|
|
{"key":{"order":"asc|desc"}}, - 参数格式:排序, key要排序的字段,order固定,取值asc或desc,不需要排序,传""
|
|
|
{"key":{"order":"asc|desc"}}
|
|
|
]
|
|
|
}
|
|
|
* @return
|
|
|
*/
|
|
|
public SearchSourceBuilder getQueryBuilder(String nestedPath, String jsonData) {
|
|
|
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
|
|
|
//什么都不传的情况下,构造查询所有的语句
|
|
|
if(StringUtils.isEmpty(jsonData)){
|
|
|
MatchAllQueryBuilder allQueryBuilder = QueryBuilders.matchAllQuery();
|
|
|
return searchSourceBuilder.query(allQueryBuilder);
|
|
|
}
|
|
|
|
|
|
JSONObject json = JSONObject.parseObject(jsonData);
|
|
|
List<Map<String, Object>> filter = (List)json.getJSONArray("filter");
|
|
|
int page = json.getIntValue("page") == 0 ? 1:json.getIntValue("page"); //从第一页开始
|
|
|
int size = json.getIntValue("size") == 0 ? 1:json.getIntValue("size"); //默认值为1,最少获取一条记录
|
|
|
JSONArray sort = json.getJSONArray("sort");
|
|
|
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
|
|
|
|
|
boolQueryBuilder = getBoolQueryBuilder(nestedPath,jsonData,false);//非嵌套的数据查询不需要nested
|
|
|
|
|
|
searchSourceBuilder.from((page -1)*size);
|
|
|
searchSourceBuilder.size(size);
|
|
|
//排序
|
|
|
if(!CollectionUtils.isEmpty(sort)){
|
|
|
for(Object obj:sort){
|
|
|
JSONObject object = JSONObject.parseObject(obj.toString());
|
|
|
FieldSortBuilder fieldSortBuilder = null;
|
|
|
for(String key:object.keySet()){
|
|
|
if(!CollectionUtils.isEmpty(fieldsMap.get(nestedPath)) && fieldsMap.get(nestedPath).contains(key)){
|
|
|
fieldSortBuilder = new FieldSortBuilder("data." + key);
|
|
|
}else{
|
|
|
fieldSortBuilder = new FieldSortBuilder(key);
|
|
|
}
|
|
|
JSONObject sortValue = object.getJSONObject(key);
|
|
|
if(StringUtils.equalsIgnoreCase(SortOrder.ASC.toString(),sortValue.getString("order"))){
|
|
|
fieldSortBuilder.order(SortOrder.ASC);
|
|
|
}else if(StringUtils.equalsIgnoreCase(SortOrder.DESC.toString(),sortValue.getString("order"))){
|
|
|
fieldSortBuilder.order(SortOrder.DESC);
|
|
|
}
|
|
|
fieldSortBuilder.setNestedPath("data");
|
|
|
searchSourceBuilder.sort(fieldSortBuilder);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(StringUtils.isNotEmpty(nestedPath)){
|
|
|
NestedQueryBuilder nestedQueryBuilder = getNestedBuilder(nestedPath,jsonData);//嵌套的数据查询
|
|
|
QueryFilterBuilder filterBuilder = QueryBuilders.queryFilter(nestedQueryBuilder);
|
|
|
QueryBuilder filteredQueryBuilder = QueryBuilders.filteredQuery(boolQueryBuilder,filterBuilder);
|
|
|
searchSourceBuilder.query(filteredQueryBuilder);
|
|
|
}else{
|
|
|
searchSourceBuilder.query(boolQueryBuilder);
|
|
|
}
|
|
|
|
|
|
return searchSourceBuilder;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 嵌套的查询query
|
|
|
* @param nestedPath
|
|
|
* @param queryCondition
|
|
|
* @return
|
|
|
*/
|
|
|
private NestedQueryBuilder getNestedBuilder(String nestedPath,String queryCondition){
|
|
|
if(StringUtils.isEmpty(nestedPath)){
|
|
|
return null;
|
|
|
}
|
|
|
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
|
|
boolQueryBuilder = getBoolQueryBuilder(nestedPath,queryCondition,true);
|
|
|
NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(nestedPath,boolQueryBuilder);
|
|
|
return nestedQueryBuilder;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 构造bool查询(里面有匹配,过滤,范围等)
|
|
|
* @param nestedPath
|
|
|
* @param queryCondition
|
|
|
* @return
|
|
|
*/
|
|
|
private BoolQueryBuilder getBoolQueryBuilder(String nestedPath,String queryCondition,Boolean isNested){
|
|
|
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
|
|
JSONObject jsonCondition = JSONObject.parseObject(queryCondition);
|
|
|
List<Map<String, Object>> filter = (List)jsonCondition.getJSONArray("filter");
|
|
|
for(Map<String, Object> param : filter) {
|
|
|
String andOr = String.valueOf(param.get("andOr"));
|
|
|
String condition = String.valueOf(param.get("condition"));
|
|
|
String field = String.valueOf(param.get("field"));
|
|
|
Object value = param.get("value");
|
|
|
|
|
|
//如果传过来的字段为空则表示查询全部
|
|
|
if(StringUtils.isEmpty(field)){
|
|
|
MatchAllQueryBuilder matchQueryBuilder = QueryBuilders.matchAllQuery();
|
|
|
boolQueryBuilder.must(matchQueryBuilder);
|
|
|
return boolQueryBuilder;
|
|
|
}
|
|
|
|
|
|
if(!isNested){
|
|
|
if(!CollectionUtils.isEmpty(fieldsMap.get(nestedPath)) && fieldsMap.get(nestedPath).contains(field)){
|
|
|
continue;
|
|
|
}
|
|
|
}else{
|
|
|
if(!CollectionUtils.isEmpty(fieldsMap.get(nestedPath)) && !fieldsMap.get(nestedPath).contains(field)){
|
|
|
continue;
|
|
|
}
|
|
|
field = nestedPath + "." + field;
|
|
|
}
|
|
|
if("null".equals(condition)){
|
|
|
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(field, value);
|
|
|
if("null".equals(andOr)) {
|
|
|
boolQueryBuilder.must(matchQueryBuilder);
|
|
|
}
|
|
|
}else if(condition.equals("=")) {
|
|
|
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(field, value);
|
|
|
if("and".equals(andOr)) {
|
|
|
boolQueryBuilder.must(matchQueryBuilder);
|
|
|
}else if("or".equals(andOr)) {
|
|
|
boolQueryBuilder.should(matchQueryBuilder);
|
|
|
}
|
|
|
}else if (condition.equals("?")) {
|
|
|
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(field + ":" + value);
|
|
|
if("and".equals(andOr)) {
|
|
|
boolQueryBuilder.must(queryStringQueryBuilder);
|
|
|
}else if("or".equals(andOr)) {
|
|
|
boolQueryBuilder.should(queryStringQueryBuilder);
|
|
|
}
|
|
|
}else {
|
|
|
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(field);
|
|
|
if(field.endsWith("Date")) {
|
|
|
rangeQueryBuilder.format("yyyy-MM-dd HH:mm:ss");
|
|
|
}
|
|
|
if(condition.equals(">")) {
|
|
|
rangeQueryBuilder.gt(value);
|
|
|
}else if(condition.equals(">=")) {
|
|
|
rangeQueryBuilder.gte(value);
|
|
|
}else if(condition.equals("<=")) {
|
|
|
rangeQueryBuilder.lte(value);
|
|
|
}else if(condition.equals("<")) {
|
|
|
rangeQueryBuilder.lt(value);
|
|
|
}
|
|
|
if("and".equals(andOr)) {
|
|
|
boolQueryBuilder.must(rangeQueryBuilder);
|
|
|
}else if("or".equals(andOr)) {
|
|
|
boolQueryBuilder.should(rangeQueryBuilder);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return boolQueryBuilder;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 构造查询所有的语句
|
|
|
* @return
|
|
|
*/
|
|
|
public SearchSourceBuilder getQueryAllBuilder(){
|
|
|
return getQueryBuilder("","");
|
|
|
}
|
|
|
|
|
|
public static void main(String args[]) {
|
|
|
|
|
|
// elasticSearchQueryGenerator.init();
|
|
|
/* String str = "{\n" +
|
|
|
"\t\"filter\": [{\n" +
|
|
|
"\t\t\"andOr\": \"and\",\n" +
|
|
|
"\t\t\"condition\": \"=\",\n" +
|
|
|
"\t\t\"field\": \"\",\n" +
|
|
|
"\t\t\"value\": \"\"\n" +
|
|
|
"\t}]\n" +
|
|
|
"}";
|
|
|
getQueryBuilder("",str);*/
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|