工作中,由于es原生java api对group的支持不是很友好,特别是group by多个字段聚合时,容易java heap space ,而使用essql则不会。但是使用essql多个group by字段,http返回的结果很复杂,嵌套太多,如果每个sql都带有group by字段,则相应的每个方法都要重写一套特定解析规范,重复造轮子,用了一下午时间,写了一套java版本的essql group by返回结果的封装类,动态适配,避免重复造轮子!有喜欢的,请点赞哈!!!
@Override public Map<String, Object> sqlQuery(String sql) { LinkedHashMap resp = null; try { HttpHeaders headers = new HttpHeaders(); headers.set("Content-Type", "text/plain"); headers.set("Authorization", "Basic enpsb2c6T09vSjNvVlVadDVFeHY="); HttpEntity<String> entity = new HttpEntity<>(sql, headers); resp = restTemplate.postForObject(logUrl, entity, LinkedHashMap.class); } catch (Exception e) { logger.error("LogRestService | sqlQuery | sql={}", sql, e); } return resp; }
/** * Handle the query result * in case of Aggregation query (SQL group by) * * @param resMap */ public static List<Map<String, Object>> aggregationQueryResultHandler(Map<String, Object> resMap) { Map<String, Object> aggregations = (Map<String, Object>) resMap.get("aggregations"); if (MapUtils.isEmpty(aggregations)) { return null; } return getRows(null, aggregations, new HashMap<>()); } private static List<Map<String, Object>> getRows(String bucketName, Map<String, Object> bucket, Map<String, Object> dataMap) { List<Map<String, Object>> rows = new ArrayList<>(); List<Map<String, Object>> subBuckets = getSubBuckets(bucket); if (subBuckets.size() > 0) { subBuckets.forEach(item -> { String subBucketName = (String) item.get("bucketName"); Map<String, Object> subBucket = (Map<String, Object>) item.get("bucket"); Map<String, Object> newDataMap = new HashMap<>(); if (StringUtils.isNotBlank(bucketName)) { newDataMap.put(bucketName, bucket.get("key")); newDataMap.putAll(dataMap); } List<Map<String, Object>> newRows = getRows(subBucketName, subBucket, newDataMap); rows.addAll(newRows); }); } else { Map<String, Object> resultMap = new HashMap<>(); resultMap.putAll(dataMap); if (StringUtils.isNotBlank(bucketName)) { if (bucket.containsKey("key_as_string")) { resultMap.put(bucketName, bucket.get("key_as_string")); } else { resultMap.put(bucketName, bucket.get("key")); } } for (String field : bucket.keySet()) { Object bucketValue = bucket.get(field); if (bucketValue instanceof Map) { Map<String, Object> tempMap = (Map<String, Object>) bucketValue; if (tempMap.containsKey("buckets")) { List<Map<String, Object>> newRows = getRows(null, tempMap, new HashMap<>()); rows.addAll(newRows); continue; } if (tempMap.containsKey("value")) { resultMap.put(field, tempMap.get("value")); } } } if (MapUtils.isNotEmpty(resultMap)) { rows.add(resultMap); } } return rows; } private static List<Map<String, Object>> getSubBuckets(Map<String, Object> bucket) { List<Map<String, Object>> mapList = new ArrayList<>(); for (String field : bucket.keySet()) { Object obj = bucket.get(field); if (obj instanceof Map && ((Map) obj).containsKey("buckets")) { List<Map<String, Object>> subList = (List<Map<String, Object>>) ((Map<String, Object>) obj).get("buckets"); subList.forEach(item -> { Map<String, Object> subMap = new HashMap<>(); subMap.put("bucketName", field); subMap.put("bucket", item); mapList.add(subMap); }); } } return mapList; }