1.ES数据聚合
聚合(aggregation)可以实现对文档数据的统计、分析、运算。聚合常见有三大类。
- 桶(Bucket)聚合:用来对文档做分组
常用的方法
语句 | 描述 |
---|---|
TermAggregation | 按照文档字段值分组 |
Date Histogram | 按照日期阶梯分组,列如一周或一月为一组 |
-
度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等
语句 描述 avg(average) 平均值 Max(maximum) 最大值 Min(minimum) 最小值 Stats(statistics) 同时求max、min、avg、sum等 -
管道(pipeline)聚合:其他聚合的结果为基础做聚合,使用较少
1.总结
什么是聚合
- 聚合是对文档数据的统计、分析、计算
聚合的常见种类有那些
- Bucket:对文档数据分组,并统计每组数量
- Metric:对文档数据做计算,列如avg
- pipeline:基于其他聚合的结果再做聚合
参与聚合的字段类型必须是
- keyword
- 数值
- 日期
- 布尔
1.1.DSL实现Bucket聚合
统计所有数据中的酒店品牌有几种。
GET /indexName/_search
{
"size":0, //设置size为0,结果中不包含hits,只包含aggregations,详细看下图
"aggs":{ //定义聚合
"brandAgg":{ //定义聚合的名称
"terms":{ //聚合的类型,详细信息查看官方文档
"field":"brand", //参与聚合的字段
"size":20 //希望获取的聚合结果数量
}
}
}
}
1.1.1.关于size的解释
-
Return only aggregation resultsedit
By default, searches containing an aggregation return both search hits and aggregation results. To return only aggregation results, set
size
to0
:只返回聚合结果:默认情况下,包含聚合的搜索将返回搜索结果和聚合结果。为了只返回聚合结果,将"size"设置为‘0’
引用自官方文档
没有指定size时就会返回每条文档的hits,下图
当指定了size为0时就只会返回Aggregation作为结果
注意:指定为0的那个size是和aggs(聚合同级别的),而aggs中的size才是指定显示条数,一般不指定这个size默认值是显示10条(拥有最多文档的那十条,说白了有点结果降序的意思),指定size之后就可以随心所欲的指定返回条数了
GET /indexName/_search
{
"size":0,
"aggs":{
"my_aggs":{
"terms":{
"field":"brand",
"size":1
}
}
}
}
默认情况下,Bucket集合会同Bucket内的文档数量,记为_count,并且按照指定的值进行排序。
GET /hotel/_search
{
"size":0,
"aggs":{
"my_aggs":{
"terms":{
"field":"brand",
"size":10,
"order":{
"_count":"asc" 按照_count升序,或者desc降序,也可以通过_key作为排序对象
}
}
}
}
}
下图
当数据量较大时,这时会非常占用内存,需要通过query条件来限定查询。
GET /hotel/_search
{
"query":{
"range":{ //范围搜索
"price":{ //对价格进行搜索
"lte":200 //less than equal 小于等于200 gle greater than equal大于等于也可以不加e代表小于或大于
}
}
},
"size":0,
"aggs":{
"my_aggs":{
"terms":{
"field":"brand",
"size":20
}
}
}
}
结果图
1.1.总结
aggs代表聚合,与query同级,此时query的作用是
- 限定聚合的文档范围
聚合必须的三要素
- 聚合名称
- 聚合类型
- 聚合字段
聚合可配置属性有:
- size:指定聚合结果数量
- order:指定聚合结果排序方式
- field:指定聚合字段
1.2.实现Metrics聚合
要求获取每个品牌的用户评分的min、max、avg等值
GET /hotel/_search
{
"size":0,
"aggs":{
"my_aggs":{ //聚合名称
"terms":{ //查询
"field":"brand",
"size":20
},
"aggs":{ //子聚合
"scoreAggs":{
"stats":{
"field":"score"
}
}
}
}
}
}
通过聚合函数中的stats来达到求最小值、最大值、和平均值等
Stats aggregation:一个多值度量聚合,计算从聚合文档中提取的数值的统计信息。
返回值包括min、max、sum、count、avg
1.3.RestAPI实现聚合
使用Java的RestClient来实现以上ES中的DSL语句,下图所示
与ES建立连接的两种方式
-
在启动类中定义以下代码自动注入的RestHighLevelClient,推荐使用,避免重复开发
@Bean public RestHighLevelClient client(){ return new RestHighLevelClient(RestClient.builder(HttpHost.create("192.168.26.131:9200"))); }
-
通过在类中设置一个方法建立连接,
//在类中声明一个成员变量 private RestHighLevelClient client; //在每个方法中定义连接的方法 client=new RestHighLevelClient(RestClient .builder(HttpHost.create("192.168.26.131:9200")));
所有代码
package cn.itcast.hotel;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.aggregations.*;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.List;
@SpringBootTest
public class HotelAggregationTest {
// @Autowired
// private RestHighLevelClient client;
private RestHighLevelClient client;
@BeforeEach
void startUp(){
client=new RestHighLevelClient(RestClient
.builder(HttpHost.create("192.168.26.131:9200")));
}
@Test
void setup() throws IOException {
//准备请求
SearchRequest request=new SearchRequest("hotel");
//DSL语句
//设置size,返回结果没有hits
request.source().size(0);
//聚合
request.source().aggregation(AggregationBuilders
.terms("my_aggs")
.field("brand")
.size(20)
);
//发出请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//解析聚合结果
Aggregations aggregations = response.getAggregations();
//根据名称获取聚合结果
Terms myAggs = aggregations.get("my_aggs");
//获取桶
List<? extends Terms.Bucket> buckets = myAggs.getBuckets();
//遍历
for (Terms.Bucket bucket : buckets) {
//获取key,也就是品牌信息
String brandName = bucket.getKeyAsString();
long docCount = bucket.getDocCount();
System.out.println(brandName);
System.out.println(docCount);
System.out.println("===================================");
}
/*
GET /hotel/_search
{
"size":0;
"aggs":{
"my_aggs":{
"terms":{
"field":"brand",
"size":20,
}
}
}
}
*/
}
}