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 to 0:

只返回聚合结果:默认情况下,包含聚合的搜索将返回搜索结果和聚合结果。为了只返回聚合结果,将"size"设置为‘0’

引用自官方文档

没有指定size时就会返回每条文档的hits,下图

java 对 es 聚合 es怎么做聚合_java

当指定了size为0时就只会返回Aggregation作为结果

java 对 es 聚合 es怎么做聚合_elasticsearch_02

注意:指定为0的那个size是和aggs(聚合同级别的),而aggs中的size才是指定显示条数,一般不指定这个size默认值是显示10条(拥有最多文档的那十条,说白了有点结果降序的意思),指定size之后就可以随心所欲的指定返回条数了

GET /indexName/_search
{
	"size":0,
	"aggs":{
		"my_aggs":{
			"terms":{
				"field":"brand",
				"size":1
			}
		}
	}
}

java 对 es 聚合 es怎么做聚合_elasticsearch_03

默认情况下,Bucket集合会同Bucket内的文档数量,记为_count,并且按照指定的值进行排序。

GET /hotel/_search
{
	"size":0,
	"aggs":{
		"my_aggs":{
			"terms":{
				"field":"brand",
				"size":10,
				"order":{
					"_count":"asc" 按照_count升序,或者desc降序,也可以通过_key作为排序对象
				}
			}
		}
	}
}

下图

java 对 es 聚合 es怎么做聚合_数据_04

当数据量较大时,这时会非常占用内存,需要通过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
			}
		}
	}
}

结果图

java 对 es 聚合 es怎么做聚合_java_05

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

java 对 es 聚合 es怎么做聚合_大数据_06

1.3.RestAPI实现聚合

使用Java的RestClient来实现以上ES中的DSL语句,下图所示

java 对 es 聚合 es怎么做聚合_elasticsearch_07

与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")));

java 对 es 聚合 es怎么做聚合_大数据_08

所有代码

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,
                    }
                }
            }
        }

      */

    }
}