ViewService.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. package com.yihu.quota.service.view;
  2. import com.fasterxml.jackson.core.type.TypeReference;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import com.yihu.ehr.elasticsearch.ElasticSearchPool;
  5. import com.yihu.ehr.exception.ApiException;
  6. import com.yihu.ehr.query.BaseJpaService;
  7. import com.yihu.quota.contants.ViewConstant;
  8. import com.yihu.quota.dao.view.ViewDao;
  9. import com.yihu.quota.dao.view.ViewDimensionDao;
  10. import com.yihu.quota.dao.view.ViewQuotaDao;
  11. import com.yihu.quota.dao.view.ViewQuotaFilterDao;
  12. import com.yihu.quota.model.cube.Cube;
  13. import com.yihu.quota.model.view.View;
  14. import com.yihu.quota.model.view.ViewDimension;
  15. import com.yihu.quota.model.view.ViewQuota;
  16. import com.yihu.quota.model.view.ViewQuotaFilter;
  17. import com.yihu.quota.service.cube.CubeService;
  18. import com.yihu.quota.vo.ViewQuotaFilterModel;
  19. import io.searchbox.core.search.aggregation.DateHistogramAggregation;
  20. import io.searchbox.core.search.aggregation.FilterAggregation;
  21. import io.searchbox.core.search.aggregation.ValueCountAggregation;
  22. import org.apache.commons.lang3.StringUtils;
  23. import org.apache.log4j.Logger;
  24. import org.elasticsearch.action.search.SearchRequestBuilder;
  25. import org.elasticsearch.action.search.SearchResponse;
  26. import org.elasticsearch.client.transport.TransportClient;
  27. import org.elasticsearch.index.query.BoolQueryBuilder;
  28. import org.elasticsearch.index.query.QueryBuilder;
  29. import org.elasticsearch.index.query.QueryBuilders;
  30. import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
  31. import org.elasticsearch.search.aggregations.AggregationBuilder;
  32. import org.elasticsearch.search.aggregations.AggregationBuilders;
  33. import org.elasticsearch.search.aggregations.Aggregations;
  34. import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
  35. import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramBuilder;
  36. import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
  37. import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
  38. import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
  39. import org.elasticsearch.search.aggregations.bucket.terms.Terms;
  40. import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
  41. import org.elasticsearch.search.aggregations.metrics.MetricsAggregationBuilder;
  42. import org.elasticsearch.search.aggregations.metrics.avg.AvgBuilder;
  43. import org.elasticsearch.search.aggregations.metrics.cardinality.Cardinality;
  44. import org.elasticsearch.search.aggregations.metrics.cardinality.CardinalityBuilder;
  45. import org.elasticsearch.search.aggregations.metrics.max.MaxBuilder;
  46. import org.elasticsearch.search.aggregations.metrics.min.MinBuilder;
  47. import org.elasticsearch.search.aggregations.metrics.sum.SumBuilder;
  48. import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCountBuilder;
  49. import org.elasticsearch.search.sort.SortBuilder;
  50. import org.springframework.beans.factory.annotation.Autowired;
  51. import org.springframework.stereotype.Service;
  52. import java.io.IOException;
  53. import java.util.ArrayList;
  54. import java.util.HashMap;
  55. import java.util.List;
  56. import java.util.Map;
  57. /**
  58. * @author janseny
  59. * @date 2018年9月26日
  60. */
  61. @Service
  62. public class ViewService extends BaseJpaService<View, ViewDao> {
  63. private static final Logger logger = Logger.getLogger(ViewService.class);
  64. @Autowired
  65. private ViewDao viewDao;
  66. @Autowired
  67. private ViewDimensionDao viewDimensionDao;
  68. @Autowired
  69. private ViewQuotaDao viewQuotaDao;
  70. @Autowired
  71. private ViewQuotaFilterDao viewQuotaFilterDao;
  72. @Autowired
  73. private ElasticSearchPool elasticSearchPool;
  74. @Autowired
  75. private ObjectMapper objectMapper;
  76. @Autowired
  77. private CubeService cubeService;
  78. public View findOne(String id) {
  79. return viewDao.findOne(id);
  80. }
  81. public View findByCode(String viewCode){
  82. return viewDao.findByCode(viewCode);
  83. }
  84. /**
  85. * 获取视图完整规则
  86. *
  87. * @param viewCode 视图编码
  88. * @return 视图规则
  89. * @author 张进军
  90. */
  91. public View getViewRule(String viewCode) {
  92. View view = viewDao.findByCode(viewCode);
  93. // 视图默认过滤条件
  94. view.setViewFilterList(viewQuotaFilterDao.findByRelationId(view.getId()));
  95. // 视图各组组内顶层行维度(升序)
  96. List<ViewDimension> groupTopRowDimensionList = viewDimensionDao.getGroupTopRowDimensionList(view.getId());
  97. view.setGroupTopRowDimensionList(groupTopRowDimensionList);
  98. // 视图各组组内其他行维度(升序)
  99. Map<Integer, List<ViewDimension>> groupOtherRowDimensionsMap = new HashMap<>(16);
  100. for (ViewDimension viewDimension : groupTopRowDimensionList) {
  101. List<ViewDimension> otherRowDimensionList = viewDimensionDao.getGroupOtherRowDimensionList(view.getId(), viewDimension.getGroupRow());
  102. groupOtherRowDimensionsMap.put(viewDimension.getGroupRow(), otherRowDimensionList);
  103. }
  104. view.setGroupOtherRowDimensionsMap(groupOtherRowDimensionsMap);
  105. // 视图列维度(升序)
  106. view.setColDimensionList(viewDimensionDao.getColDimensionList(view.getId()));
  107. // 视图指标
  108. view.setViewQuotaList(viewQuotaDao.findByViewId(view.getId()));
  109. for (ViewQuota viewQuota : view.getViewQuotaList()) {
  110. List<ViewQuotaFilter> quotaFilterList = viewQuotaFilterDao.findByRelationId(viewQuota.getId());
  111. viewQuota.setQuotaFilterList(quotaFilterList);
  112. }
  113. return view;
  114. }
  115. /**
  116. * 获取视图统计结果
  117. *
  118. * @param viewCode 视图编码
  119. * @param filterModelList 页面的过滤条件模型集合
  120. * @return ES聚合对象
  121. * @author 张进军
  122. */
  123. public Aggregations statViewResult(String viewCode, List<ViewQuotaFilterModel> filterModelList) throws Exception {
  124. // 获取视图规则
  125. View view = this.getViewRule(viewCode);
  126. String[] esIndices = view.getEsIndex().split(",");
  127. String[] esTypes = view.getEsType().split(",");
  128. int indexCount = esIndices.length;
  129. TransportClient transportClient = elasticSearchPool.getClient();
  130. SearchRequestBuilder searchRequestBuilder = transportClient.prepareSearch(esIndices).setTypes(esTypes).setSize(0);
  131. // 组装页面传入的过滤条件
  132. BoolQueryBuilder viewBoolQueryBuilder = QueryBuilders.boolQuery();
  133. this.joinFilters(viewBoolQueryBuilder, filterModelList);
  134. // 组装视图默认过滤条件
  135. String viewFilterStr = objectMapper.writeValueAsString(view.getViewFilterList());
  136. List<ViewQuotaFilterModel> viewFilterModelList = objectMapper.readValue(viewFilterStr, new TypeReference<List<ViewQuotaFilterModel>>() {
  137. });
  138. this.joinFilters(viewBoolQueryBuilder, viewFilterModelList);
  139. searchRequestBuilder.setQuery(viewBoolQueryBuilder);
  140. // 视图的顶层行维度
  141. List<ViewDimension> groupTopRowDimensionList = view.getGroupTopRowDimensionList();
  142. // 视图的组内其他行维度
  143. Map<Integer, List<ViewDimension>> groupOtherRowDimensionsMap = view.getGroupOtherRowDimensionsMap();
  144. // 视图的列维度
  145. List<ViewDimension> colDimensionList = view.getColDimensionList();
  146. // 视图的指标
  147. List<ViewQuota> viewQuotaList = view.getViewQuotaList();
  148. //region 聚合组装
  149. if (groupTopRowDimensionList.size() == 0) {
  150. if (!"1".equals(view.getDisplayType())) {
  151. // 视图展示为非数值类型场合
  152. throw new ApiException("请为视图至少配置一个行维度。");
  153. } else if (viewQuotaList == null || viewQuotaList.size() == 0) {
  154. throw new ApiException("请为视图至少配置一个指标。");
  155. } else {
  156. // 视图展示为数值类型的场合
  157. // 如果有多个多维数据集时,添加指标的过滤条件,指定其数据来自哪个多维数据集。
  158. if (indexCount > 1) {
  159. for (ViewQuota quota : viewQuotaList) {
  160. ViewQuotaFilter indexFilter = new ViewQuotaFilter();
  161. indexFilter.setDimensionCode("_index");
  162. indexFilter.setCompareType("and");
  163. indexFilter.setCompareType("belong");
  164. indexFilter.setFilterValue(quota.getEsIndex());
  165. quota.getQuotaFilterList().add(indexFilter);
  166. ViewQuotaFilter typeFilter = new ViewQuotaFilter();
  167. typeFilter.setDimensionCode("_type");
  168. typeFilter.setCompareType("and");
  169. typeFilter.setCompareType("belong");
  170. typeFilter.setFilterValue(quota.getEsType());
  171. quota.getQuotaFilterList().add(typeFilter);
  172. }
  173. }
  174. // 因为该场合没有行/列维度,直接对指标聚合。
  175. List<AbstractAggregationBuilder> quotaAggList = this.gatherQuotaMetricsAgg(viewQuotaList, null);
  176. for (AbstractAggregationBuilder quotaAgg : quotaAggList) {
  177. searchRequestBuilder.addAggregation(quotaAgg);
  178. }
  179. }
  180. } else {
  181. // 遍历顶层行维度
  182. for (ViewDimension topRowDimension : groupTopRowDimensionList) {
  183. // 有多个多维度数据集时,设定顶层行维度聚合的数据来自哪个多维数据集。
  184. FilterAggregationBuilder topFilterAgg = null;
  185. if (indexCount > 1) {
  186. String aggName = topRowDimension.getDimensionCode() + "-filter";
  187. QueryBuilder indexQueryBuilder = QueryBuilders.termQuery("_index", topRowDimension.getEsIndex());
  188. QueryBuilder typeQueryBuilder = QueryBuilders.termQuery("_type", topRowDimension.getEsType());
  189. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  190. boolQueryBuilder.must(indexQueryBuilder);
  191. boolQueryBuilder.must(typeQueryBuilder);
  192. topFilterAgg = AggregationBuilders.filter(aggName).filter(boolQueryBuilder);
  193. }
  194. // 顶层行维度聚合
  195. AggregationBuilder topAgg = this.joinDimensionAgg(topRowDimension);
  196. // 遍历同组其他行维度,其聚合按顺序嵌套于同组上层行维度聚合下。
  197. // 倒序遍历的上一个行维度聚合
  198. AggregationBuilder preRowAgg = null;
  199. List<ViewDimension> otherRowDimensionList = groupOtherRowDimensionsMap.get(topRowDimension.getGroupRow());
  200. if (otherRowDimensionList != null && otherRowDimensionList.size() > 0) {
  201. int otherRowDimensionCount = otherRowDimensionList.size();
  202. for (int i = otherRowDimensionCount - 1; i > 0; i--) {
  203. ViewDimension otherRowDimension = otherRowDimensionList.get(i);
  204. AggregationBuilder rowAgg = this.joinDimensionAgg(otherRowDimension);
  205. if (i == otherRowDimensionCount - 1) {
  206. // 末端行维度场合
  207. // 汇总列维度的聚合及嵌套其指标聚合,并列嵌套于末端行维度的聚合。
  208. this.gatherColDimensionsAndQuotasAgg(rowAgg, otherRowDimension, colDimensionList, viewQuotaList);
  209. preRowAgg = rowAgg;
  210. } else {
  211. rowAgg.subAggregation(preRowAgg);
  212. preRowAgg = rowAgg;
  213. }
  214. topAgg.subAggregation(rowAgg);
  215. }
  216. } else {
  217. // 行维度组内只有一个行维度的场合
  218. // 汇总列维度的聚合及嵌套其指标聚合,并列嵌套于顶层行维度的聚合。
  219. this.gatherColDimensionsAndQuotasAgg(topAgg, topRowDimension, colDimensionList, viewQuotaList);
  220. }
  221. if (topFilterAgg != null) {
  222. topFilterAgg.subAggregation(topAgg);
  223. searchRequestBuilder.addAggregation(topFilterAgg);
  224. } else {
  225. searchRequestBuilder.addAggregation(topAgg);
  226. }
  227. }
  228. }
  229. //endregion 聚合组装
  230. SearchResponse searchResponse = searchRequestBuilder.get();
  231. Aggregations aggregations = searchResponse.getAggregations();
  232. transportClient.close();
  233. return aggregations;
  234. }
  235. /**
  236. * 拼接视图/指标的过滤条件
  237. *
  238. * @param boolQueryBuilder ES布尔查询构建器
  239. * @param filterModelList 视图/指标的过滤条件模型集合
  240. */
  241. private void joinFilters(BoolQueryBuilder boolQueryBuilder, List<ViewQuotaFilterModel> filterModelList) {
  242. if (filterModelList != null && filterModelList.size() != 0) {
  243. for (ViewQuotaFilterModel filterModel : filterModelList) {
  244. String field = filterModel.getDimensionCode();
  245. Object value = filterModel.getFilterValue();
  246. // 属于与否
  247. if ("belong".equals(filterModel.getCompareType())) {
  248. QueryBuilder queryBuilder = QueryBuilders.termQuery(field, value);
  249. joinBoolQuery(boolQueryBuilder, queryBuilder, filterModel.getRelationType());
  250. } else if ("not_belong".equals(filterModel.getCompareType())) {
  251. QueryBuilder queryBuilder = QueryBuilders.termQuery(field, value);
  252. joinBoolQuery(boolQueryBuilder, queryBuilder, "not");
  253. }
  254. // 为空与否
  255. else if ("null".equals(filterModel.getCompareType())) {
  256. QueryBuilder queryBuilder = QueryBuilders.missingQuery(field).nullValue(true);
  257. joinBoolQuery(boolQueryBuilder, queryBuilder, filterModel.getRelationType());
  258. } else if ("not_null".equals(filterModel.getCompareType())) {
  259. QueryBuilder queryBuilder = QueryBuilders.missingQuery(field).nullValue(true);
  260. joinBoolQuery(boolQueryBuilder, queryBuilder, "not");
  261. }
  262. // 包含与否
  263. else if ("null".equals(filterModel.getCompareType())) {
  264. QueryBuilder queryBuilder = QueryBuilders.matchQuery(field, value);
  265. joinBoolQuery(boolQueryBuilder, queryBuilder, filterModel.getRelationType());
  266. } else if ("not_null".equals(filterModel.getCompareType())) {
  267. QueryBuilder queryBuilder = QueryBuilders.matchQuery(field, value);
  268. joinBoolQuery(boolQueryBuilder, queryBuilder, "not");
  269. }
  270. // 范围
  271. else if ("gt".equals(filterModel.getCompareType())) {
  272. QueryBuilder queryBuilder = QueryBuilders.rangeQuery(field).gt(value);
  273. joinBoolQuery(boolQueryBuilder, queryBuilder, filterModel.getRelationType());
  274. } else if ("gte".equals(filterModel.getCompareType())) {
  275. QueryBuilder queryBuilder = QueryBuilders.rangeQuery(field).gte(value);
  276. joinBoolQuery(boolQueryBuilder, queryBuilder, filterModel.getRelationType());
  277. } else if ("lt".equals(filterModel.getCompareType())) {
  278. QueryBuilder queryBuilder = QueryBuilders.rangeQuery(field).lt(value);
  279. joinBoolQuery(boolQueryBuilder, queryBuilder, filterModel.getRelationType());
  280. } else if ("lte".equals(filterModel.getCompareType())) {
  281. QueryBuilder queryBuilder = QueryBuilders.rangeQuery(field).lte(value);
  282. joinBoolQuery(boolQueryBuilder, queryBuilder, filterModel.getRelationType());
  283. }
  284. }
  285. }
  286. }
  287. /**
  288. * 组装且/或/否查询
  289. *
  290. * @param boolQueryBuilder ES布尔查询构建器
  291. * @param queryBuilder ES查询构建器
  292. * @param relationType 且/或/非关系类型
  293. */
  294. private void joinBoolQuery(BoolQueryBuilder boolQueryBuilder, QueryBuilder queryBuilder, String relationType) {
  295. if ("and".equals(relationType)) {
  296. boolQueryBuilder.must(queryBuilder);
  297. } else if ("or".equals(relationType)) {
  298. boolQueryBuilder.should(queryBuilder);
  299. } else if ("not".equals(relationType)) {
  300. boolQueryBuilder.mustNot(queryBuilder);
  301. }
  302. }
  303. /**
  304. * 组装行/列维度的聚合
  305. *
  306. * @param viewDimension 视图行/列维度
  307. * @return 行/列维度的聚合构建器
  308. */
  309. private AggregationBuilder joinDimensionAgg(ViewDimension viewDimension) {
  310. AggregationBuilder dimensionAgg = null;
  311. String dimensionCode = viewDimension.getDimensionCode();
  312. String orderType = viewDimension.getMemberOrderType();
  313. String orderStrategy = viewDimension.getMemberOrderStrategy();
  314. boolean isAsc = StringUtils.isEmpty(orderStrategy) || "asc".equals(orderStrategy) ? true : false;
  315. String memberOrderQuotaId = viewDimension.getMemberOrderQuotaId();
  316. Integer memberCount = viewDimension.getMemberCount();
  317. String fieldType = cubeService.findDimensionDataType(viewDimension.getCubeCode(), dimensionCode);
  318. if (!"date".equals(fieldType)) {
  319. String aggName = dimensionCode + "-terms";
  320. dimensionAgg = AggregationBuilders.terms(aggName).field(dimensionCode);
  321. // 设置排序
  322. if (StringUtils.isEmpty(orderType) || "name".equals(orderType)) {
  323. ((TermsBuilder) dimensionAgg).order(Terms.Order.term(isAsc));
  324. } else {
  325. // 按子聚合结果排序,拼接子聚合路径
  326. if (StringUtils.isNotEmpty(memberOrderQuotaId)) {
  327. ViewQuota viewQuota = viewQuotaDao.findOne(memberOrderQuotaId);
  328. if ("basic".equals(viewQuota.getFormulaMode())) {
  329. String subAggPath = viewQuota.getBasicFormulaType() + "-result";
  330. ((TermsBuilder) dimensionAgg).order(Terms.Order.aggregation(subAggPath, isAsc));
  331. } else {
  332. ((TermsBuilder) dimensionAgg).order(Terms.Order.term(isAsc));
  333. }
  334. }
  335. }
  336. // 设置分组个数
  337. if (memberCount != null && memberCount > 0) {
  338. ((TermsBuilder) dimensionAgg).size(memberCount);
  339. } else {
  340. // TODO 需动态获取全部的分组个数进行设置
  341. ((TermsBuilder) dimensionAgg).size(1000);
  342. }
  343. } else {
  344. String aggName = dimensionCode + "-date_histogram";
  345. dimensionAgg = AggregationBuilders.dateHistogram(aggName).field(dimensionCode);
  346. ((DateHistogramBuilder) dimensionAgg).minDocCount(0);
  347. ((DateHistogramBuilder) dimensionAgg).format(viewDimension.getMemberDateFormat());
  348. ((DateHistogramBuilder) dimensionAgg).interval(new DateHistogramInterval(viewDimension.getMemberDateInterval()));
  349. // 设置排序
  350. Histogram.Order order = isAsc ? Histogram.Order.KEY_ASC : Histogram.Order.KEY_DESC;
  351. if (StringUtils.isEmpty(orderType) || "name".equals(orderType)) {
  352. ((DateHistogramBuilder) dimensionAgg).order(order);
  353. } else {
  354. // 按子聚合结果排序,拼接子聚合路径
  355. if (StringUtils.isNotEmpty(memberOrderQuotaId)) {
  356. ViewQuota viewQuota = viewQuotaDao.findOne(memberOrderQuotaId);
  357. if ("basic".equals(viewQuota.getFormulaMode())) {
  358. String subAggPath = viewQuota.getBasicFormulaType() + "-result";
  359. ((DateHistogramBuilder) dimensionAgg).order(Histogram.Order.aggregation(subAggPath, isAsc));
  360. } else {
  361. ((DateHistogramBuilder) dimensionAgg).order(order);
  362. }
  363. }
  364. }
  365. // TODO 动态根据条件范围设置,或设置默认值
  366. // ((DateHistogramBuilder) dimensionAgg).extendedBounds("", "");
  367. }
  368. return dimensionAgg;
  369. }
  370. /**
  371. * 汇总列维度的聚合及嵌套其指标聚合,并列嵌套于上层聚合
  372. *
  373. * @param upperAgg 上层维度的聚合构建器
  374. * @param rowViewDimension 视图的行维度
  375. * @param colDimensionList 视图的列维度集合
  376. * @param viewQuotaList 视图的指标集合
  377. * @throws IOException
  378. */
  379. private void gatherColDimensionsAndQuotasAgg(AggregationBuilder upperAgg,
  380. ViewDimension rowViewDimension,
  381. List<ViewDimension> colDimensionList,
  382. List<ViewQuota> viewQuotaList) throws IOException {
  383. if (colDimensionList != null && colDimensionList.size() != 0) {
  384. // 组装列维度的聚合
  385. for (ViewDimension colDimension : colDimensionList) {
  386. AggregationBuilder calAgg = this.joinDimensionAgg(colDimension);
  387. // 在列维度聚合上,嵌套指标的聚合
  388. List<AbstractAggregationBuilder> quotaAggList = this.gatherQuotaMetricsAgg(viewQuotaList, colDimension);
  389. for (AbstractAggregationBuilder quotaAgg : quotaAggList) {
  390. calAgg.subAggregation(quotaAgg);
  391. }
  392. upperAgg.subAggregation(calAgg);
  393. }
  394. } else {
  395. // 没有列维度的场合,在上层行维度聚合上,嵌套指标的聚合
  396. List<AbstractAggregationBuilder> quotaAggList = this.gatherQuotaMetricsAgg(viewQuotaList, rowViewDimension);
  397. for (AbstractAggregationBuilder quotaAgg : quotaAggList) {
  398. upperAgg.subAggregation(quotaAgg);
  399. }
  400. }
  401. }
  402. /**
  403. * 汇总指标的度量聚合
  404. *
  405. * @param viewQuotaList 视图的指标
  406. * @param viewDimension 视图的行/列维度
  407. * @return 指标的度量聚合构建器集合
  408. * @throws IOException
  409. */
  410. private List<AbstractAggregationBuilder> gatherQuotaMetricsAgg(List<ViewQuota> viewQuotaList,
  411. ViewDimension viewDimension) throws IOException {
  412. List<AbstractAggregationBuilder> quotaAggList = new ArrayList<>();
  413. for (ViewQuota quota : viewQuotaList) {
  414. if ("basic".equals(quota.getFormulaMode())) {
  415. String aggNamePre = "";
  416. if (viewDimension == null) {
  417. // 视图展示为数值类型的场合
  418. aggNamePre += quota.getCode() + "-";
  419. }
  420. if ("sum".equals(quota.getBasicFormulaType())) {
  421. // 求和
  422. String aggName = aggNamePre + "sum-result";
  423. SumBuilder sumAgg = AggregationBuilders.sum(aggName).field(quota.getDimensionCode());
  424. quotaAggList.add(this.joinMetricAgg(sumAgg, quota));
  425. } else if ("count".equals(quota.getBasicFormulaType())) {
  426. // 计数
  427. String aggName = aggNamePre + "count-result";
  428. ValueCountBuilder countAgg = AggregationBuilders.count(aggName).field(quota.getDimensionCode());
  429. quotaAggList.add(this.joinMetricAgg(countAgg, quota));
  430. } else if ("avg".equals(quota.getBasicFormulaType())) {
  431. // 均值
  432. String aggName = aggNamePre + "avg-result";
  433. AvgBuilder avgAgg = AggregationBuilders.avg(aggName).field(quota.getDimensionCode());
  434. quotaAggList.add(this.joinMetricAgg(avgAgg, quota));
  435. } else if ("max".equals(quota.getBasicFormulaType())) {
  436. // 最大值
  437. String aggName = aggNamePre + "max-result";
  438. MaxBuilder maxAgg = AggregationBuilders.max(aggName).field(quota.getDimensionCode());
  439. quotaAggList.add(this.joinMetricAgg(maxAgg, quota));
  440. } else if ("min".equals(quota.getBasicFormulaType())) {
  441. // 最小值
  442. String aggName = aggNamePre + "min-result";
  443. MinBuilder minAgg = AggregationBuilders.min(aggName).field(quota.getDimensionCode());
  444. quotaAggList.add(this.joinMetricAgg(minAgg, quota));
  445. } else if ("cardinality".equals(quota.getBasicFormulaType())) {
  446. // 去重计数
  447. String aggName = aggNamePre + "cardinality-result";
  448. CardinalityBuilder cardinalityAgg = AggregationBuilders.cardinality(aggName).field(quota.getDimensionCode());
  449. quotaAggList.add(this.joinMetricAgg(cardinalityAgg, quota));
  450. }
  451. }
  452. }
  453. return quotaAggList;
  454. }
  455. /**
  456. * 组装度量聚合
  457. *
  458. * @param metricAgg ES度量聚合构建器
  459. * @param quota 视图指标
  460. * @throws IOException
  461. */
  462. private AbstractAggregationBuilder joinMetricAgg(MetricsAggregationBuilder metricAgg, ViewQuota quota) throws IOException {
  463. List<ViewQuotaFilter> quotaFilterList = quota.getQuotaFilterList();
  464. FilterAggregationBuilder filterAgg = null;
  465. if (quotaFilterList != null && quotaFilterList.size() > 0) {
  466. String quotaFilterStr = objectMapper.writeValueAsString(quotaFilterList);
  467. List<ViewQuotaFilterModel> quotaFilterModelList = objectMapper.readValue(quotaFilterStr, new TypeReference<List<ViewQuotaFilterModel>>() {
  468. });
  469. BoolQueryBuilder quotaBoolQueryBuilder = QueryBuilders.boolQuery();
  470. this.joinFilters(quotaBoolQueryBuilder, quotaFilterModelList);
  471. String aggName = quota.getCode() + "-filter";
  472. filterAgg = AggregationBuilders.filter(aggName).filter(quotaBoolQueryBuilder);
  473. filterAgg.subAggregation(metricAgg);
  474. }
  475. if (filterAgg == null) {
  476. return metricAgg;
  477. } else {
  478. return filterAgg;
  479. }
  480. }
  481. }