|  | @ -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);*/
 | 
	
		
			
				|  |  |     }
 | 
	
		
			
				|  |  | 
 | 
	
		
			
				|  |  | }
 | 
	
		
			
				|  |  | 
 |