只寫了後臺,前端請求帶上dateType給後臺,後端返回封裝了json字符串的map
GsonUtil.getJsonStringByObject()是封裝的Gson.toJson的方法
前端接受解析結果 並設置echatrs參數 即可完成圖表繪製
/**
* 消息趨勢統計 dateType由前端傳遞 包括年月周
* 按年則統計過去12個月
* 按月則統計過去30天
* 按周則統計過去7天
**/
public Map<String, String> msgTrendCount(String dateType) {
//每個索引的時間field name 可能不同 根據索引設置
String rangeField = "messageSendTime";
//索引名
String index = EsIndexName.TG_MESSAGE.getIndexName();
return dateHistogram(rangeField, dateType, index);
}
private Map<String, String> dateHistogram(String rangeField, String dateType, String... indices) {
Map<String, String> map = new HashMap<>(4);
try {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
String from;
//extended bounds參數
String boundsStart;
String boundsEnd;
String to = formatter.format(now);
String format = "yyyy-MM-dd";
//bounds的格式化類型需要和format相同
DateTimeFormatter boundsFormatter = DateTimeFormatter.ofPattern(format);
//間隔 年類型較爲特殊
DateHistogramInterval interval = DateHistogramInterval.DAY;
switch (dateType) {
case "week": {
from = formatter.format(now.minusDays(6));
boundsStart = boundsFormatter.format(now.minusDays(6));
boundsEnd = boundsFormatter.format(now);
break;
}
case "year": {
from = formatter.format(now.minusMonths(11));
format = "yyyy-MM";
boundsFormatter = DateTimeFormatter.ofPattern(format);
interval = DateHistogramInterval.MONTH;
boundsStart = boundsFormatter.format(now.minusMonths(11));
boundsEnd = boundsFormatter.format(now);
break;
}
case "month":
default: {
from = formatter.format(now.minusDays(29));
boundsStart = boundsFormatter.format(now.minusDays(29));
boundsEnd = boundsFormatter.format(now);
break;
}
}
//範圍查詢
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.rangeQuery(rangeField).from(from).to(to));
//dateHistogram
AggregationBuilder aggregationBuilder = AggregationBuilders.dateHistogram("dateHistogram")//自定義名稱
.dateHistogramInterval(interval)//設置間隔
.minDocCount(0)//返回空桶
.field(rangeField)//指定時間字段
.format(format)//設定返回格式
.extendedBounds(new ExtendedBounds(boundsStart, boundsEnd));//設定範圍
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//指定size爲0 不返回文檔 因爲只需要數量
searchSourceBuilder.query(boolQueryBuilder).aggregation(aggregationBuilder).size(0);
SearchRequest searchRequest = new SearchRequest();
searchRequest.source(searchSourceBuilder);
searchRequest.indices(indices);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregation agg = searchResponse.getAggregations().get("dateHistogram");
List<? extends Histogram.Bucket> buckets = ((Histogram) agg).getBuckets();
List<String> dateList = new ArrayList<>(30);
List<String> countList = new ArrayList<>(30);
for (Histogram.Bucket bucket : buckets) {
// maybe:如果不是年 則將key中的年份去掉
dateList.add(bucket.getKeyAsString());
countList.add(String.valueOf(bucket.getDocCount()));
}
map.put("chartTime", GsonUtil.getJsonStringByObject(dateList));
map.put("chartCount", GsonUtil.getJsonStringByObject(countList));
} catch (Exception e) {
log.error("統計日期直方圖出錯:" + e.getMessage());
}
return map;
}
之前費勁寫的好多代碼來做這個統計,分別用日期去一天天的查數量,最近學習瞭解了es自帶的 date_histogram
完全契合需求,遂將原笨拙的代碼刪除改爲es的自帶聚合 (果然人還是要多讀書呀。。。)
速度上目前文檔數量不大,沒有差別,但預計隨着後期文檔數量增加,肯定是es的聚合更加高效。