在新的 API Java 客户端中创建聚合时,我遇到了一个问题。 这就是我创建请求的方式。我的一些字段名称是字符串类型。有些可以是长的或双的等
Map<String, Aggregation> termsAggregationMap= new HashMap<>();
for (String fieldName : fieldNames)
{
Aggregation termsAggregation = new Aggregation.Builder()
.terms(new TermsAggregation.Builder().field(fieldName).order(
NamedValue.of("_key", SortOrder.Asc))
.build())
.build();
map.put(fieldName, termsAggregation);
}
SearchRequest searchRequest = new SearchRequest.Builder()
.index(indexAliasName).size(0)
.aggregations(termsAggregationMap)
.build();
当我阅读它时,我发现我必须知道聚合类型:string、long、double 等..
例如,为了读取字符串的聚合,我需要使用 sterms
Map<String, Aggregate> aggregationsMap = searchResponse.aggregations();
Aggregate aggregation = aggregationsMap.get(aggregationName);
for (var entry : termAggregation.sterms().buckets().array())
{
//does something with it
entry.key().stringValue();
entry.docCount();
}
但为了获得长期价值,我需要使用lterms方法
termAggregation.lterms().buckets().array()
有没有更好的方法来做一件通用的事情,而不是像旧客户端那样每次都检查聚合类型?
我探索了你的问题。我找不到更好的方法来通用化解决方案。 lterms、sterms、dateHistogram 等方法不可通用(还有 isLterms、isSterms、isDateHistogram 等方法)
所以我的解决方案是枚举
public enum AggregationKind {
TERMS_STRING {
@Override
boolean identify(Aggregate aggregation) {
return aggregation.isSterms();
}
@Override
MultiBucketAggregateBase<?> getSpecificAggregation(Aggregate aggregation) {
return aggregation.sterms();
}
},
TERMS_LONG {
@Override
boolean identify(Aggregate aggregation) {
return aggregation.isLterms();
}
@Override
MultiBucketAggregateBase<?> getSpecificAggregation(Aggregate aggregation) {
return aggregation.lterms();
}
},
DATA_HISTOGRAM {
@Override
boolean identify(Aggregate aggregation) {
return aggregation.isDateHistogram();
}
@Override
MultiBucketAggregateBase<?> getSpecificAggregation(Aggregate aggregation) {
return aggregation.dateHistogram();
}
};
abstract boolean identify(Aggregate aggregation);
abstract MultiBucketAggregateBase<?> getSpecificAggregation(
Aggregate aggregation);
public static List<?> getBucketList(Aggregate aggregation) {
AggregationKind[] aggregationKinds = AggregationKind.values();
for (AggregationKind aggregationKind : aggregationKinds) {
if (aggregationKind.identify(aggregation)) {
MultiBucketAggregateBase<?> specificAggregation = aggregationKind
.getSpecificAggregation(aggregation);
return specificAggregation.buckets().array();
}
}
return Collections.emptyList();
}
}
使用
SearchResponse<Void> response = elasticsearchClient.search(searchRequest, Void.class);
List<StringTermsBucket> buckets = (List<StringTermsBucket>) AggregationKind
.getBucketList(response.aggregations().get(aggregationName));
如您所见,此解决方案适用于所有 Elasticsearch 存储桶聚合(
MultiBucketAggregateBase
子类(直接和传递))