一、首先在pom中先引入es8的java依赖
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.14.2</version>
</dependency>
版本可根据需要连接的es自己调整
二、配置文件添加
spring
elasticsearch:
rest:
uris: http://连接地址:9200
这部分是我当时连接es7时使用的一直没有修改,但是也可以正常使用,如果有问题欢迎大佬指正
三、创建es连接工具类
public static ElasticsearchClient initClient(){
String hostname = "链接地址";//链接地址
int port = 9200;
String username = "test";//用户名
String password = "rMv5T*rxDsdW7zy06*==";//密码
// 基本的用户名密码认证
BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
basicCredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostname, port, "http"));
restClientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder ->
httpAsyncClientBuilder.setDefaultCredentialsProvider(basicCredentialsProvider));
RestClient restClient = restClientBuilder.build();
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
ElasticsearchClient esClient = new ElasticsearchClient(transport);
return esClient;
}
四、聚合查询
java api代码
@GetMapping("/testJkEs")
@ApiOperation(value = "es聚合查询")
@ResponseBody
public void searchResponse() throws IOException {
ElasticsearchClient esClient = initClient();
Query query = RangeQuery.of(m -> m
.field("age")
.lte(JsonData.fromJson(String.valueOf(46)))
)._toQuery();
SearchResponse<EsUser> response = esClient.search(b -> b
.index("employee")
.size(0)
.query(query)
.aggregations("ages", a -> a
.terms(h -> h
.field("name")
.size(20)
.order(new NamedValue<>("_count", co.elastic.clients.elasticsearch._types.SortOrder.Asc))
).aggregations("sous",t -> t.max(h -> h
.field("age")))
),
EsUser.class
);
// 处理响应
if (response != null && response.aggregations() != null) {
StringTermsAggregate ages = response.aggregations().get("ages").sterms();
List<StringTermsBucket> array = ages.buckets().array();
for (StringTermsBucket back:array){
System.out.println(back.docCount()+"--"+back.key().stringValue());
MaxAggregate sous = back.aggregations().get("sous").max();
System.out.println(sous.value());
}
}
}
对应的kibana中的查询语句
GET /employee/_search
{
"query": {
"range": {
"age": {
"lte": 46
}
}
},
"size": 0,
"aggs": {
"ages": {
"terms": {
"field": "name",
"order": {
"_count": "asc"
},
"size": 20
},
"aggs": {
"score_stats": {
"max": {
"field": "age"
}
}
}
}
}
}
JavaApi代码因为我这是测试代码所以直接在controller里边写了,实际项目可以自己常见接口及实现层的代码,下边对代码进行解析(自己也可以把代码粘贴进大数据模型中让AI解析,内容都是差不多的)
kibana代码中的aggs是aggregations的缩写写哪一个都可以
1、请求数据
Query query = RangeQuery.of(m -> m
.field("age")
.lte(JsonData.fromJson(String.valueOf(46)))
)._toQuery();
这里创建了一个范围查询 (RangeQuery
),它会查找 age
字段值小于或等于 46 的文档。JsonData.fromJson(String.valueOf(46))
将整数值转换为 Elasticsearch 能够识别的 JSON 数据类型,直接写46的话类型会不对。
SearchResponse<EsUser> response = esClient.search(b -> b
.index("employee")
.size(0)
.query(query)
.aggregations("ages", a -> a
.terms(h -> h
.field("name")
.size(20)
.order(new NamedValue<>("_count", co.elastic.clients.elasticsearch._types.SortOrder.Asc))
).aggregations("sous",t -> t.max(h -> h
.field("age")))
),
EsUser.class
);
.index指定了要搜索的索引名称是 "employee"
。
.size表示不返回实际的文档,而只是获取聚合结果。
.query应用了之前创建的范围查询条件到搜索请求中。
.aggregations定义了一个名为 "ages"
的术语聚合 (terms aggregation
),它会基于 name
字段的值来分组数据,并且每个桶(bucket)最多包含 20 个不同的键值。术语聚合内部又嵌套了一个名为 "sous"
的最大值聚合 (max aggregation
),它计算每个 name
分组内 age
字段的最大值。
.order表示查询结果降序排列,正序的话可以不写也可以将asc改为desc
EsUser.class返回的数据对象,如果不返回就是用Void.class
2、返回结果解析
response.aggregations().get("ages").sterms();
获取聚合名称为ages的聚合结果
List<StringTermsBucket> array = ages.buckets().array();
获取桶内容列表(分组信息)
System.out.println(back.docCount()+"--"+back.key().stringValue());
获取每个桶(分组)中的文档统计数据和分组键内容信息, back.key()后边跟的xxxValue()可以根据自己的实际情况选择使用string或其他数据类型
MaxAggregate sous = back.aggregations().get("sous").max();
获取嵌套循环中自定义为“sous”的聚合查询,后边的max可以根据自己的情况调整为avg、min或其他内容
以上就实现了一个es8-JavaApi的聚合查询代码,有没有其他更好的实现方法本人不知道,也希望大佬来指教。以上代码是参考官网代码,具体路径如下Aggregations | Elasticsearch Java API Client [8.14] | Elastic