最近用到es做人群画像,原始数据是带标签的pin包,为了方便查询,对数据做了预处理,按标签做聚合,由于标签的数量不固定,所以想起来用递归实现多字段聚合(三个及三个以上字段),源码在此,方便大家参阅。类似group by field1,field2,field3...
Note:groupFields存放聚合的字段
List<String> groupFields = new ArrayList<>();
groupFields.add("字段1");
groupFields.add("字段2");
groupFields.add("字段3");
TermsBuilder termsBuilder = AggregationBuilders.terms(groupFields.get(0)).field(groupFields.get(0)).size(100);
subAgg(groupFields, termsBuilder, 0);
SearchResponse response = client.prepareSearch(INDEX_NAME).addAggregation(termsBuilder).setSize(0).execute().actionGet(60000);
Terms terms = response.getAggregations().get(groupFields.get(0));
for (Terms.Bucket bucket : terms.getBuckets()) {
StringBuilder builder = new StringBuilder();
builder.append(bucket.getKey()).append("\t");
resolveResult(bucket, groupFields, builder);
}
//拼装聚合条件
private void subAgg(List<String> list, TermsBuilder termsBuilder, int count) {
if (count < list.size() - 1) {
count ++;
TermsBuilder termsBuilder1 = AggregationBuilders.terms(list.get(count)).field(list.get(count)).size(GROUP_SIZE);
termsBuilder.subAggregation(termsBuilder1);
subAgg(list, termsBuilder1, count);
}
}
//聚合结果解析
private void resolveResult(Terms.Bucket bucket, List<String> list, StringBuilder keys) {
boolean flag = false;
for (String field : list) {
Terms terms = bucket.getAggregations().get(field);
if (terms != null) {
for (Terms.Bucket bucket1 : terms.getBuckets()) {
StringBuilder keys1 = new StringBuilder();
keys1.append(keys).append(bucket1.getKey()).append("\t");
resolveResult(bucket1, list, keys1);
}
flag = true;
break;
}
}
if (!flag) {
String record =
LOGGER.info("keys = {}", keys);
}
}