ElasticSearch5.X尝试聚合(一)

尝试聚合

我们可以用以下几页定义不同的聚合和它们的语法, 但学习聚合的最佳途径就是用实例来说明。 一旦我们获得了聚合的思想,以及如何合理地嵌套使用它们,那么语法就变得不那么重要了。

注意

聚合的桶操作和度量的完整用法可以在 Elasticsearch 参考 中找到。本章中会涵盖其中很多内容,但在阅读完本章后查看它会有助于我们对它的整体能力有所了解。

所以让我们先看一个例子。我们将会创建一些对汽车经销商有用的聚合,数据是关于汽车交易的信息:车型、制造商、售价、何时被出售等。

首先我们批量索引一些数据:

POST /cars/transactions/_bulk
{ "index": {}}
{ "price" : 10000, "color" : "red", "make" : "honda", "sold" : "2014-10-28" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
{ "index": {}}
{ "price" : 30000, "color" : "green", "make" : "ford", "sold" : "2014-05-18" }
{ "index": {}}
{ "price" : 15000, "color" : "blue", "make" : "toyota", "sold" : "2014-07-02" }
{ "index": {}}
{ "price" : 12000, "color" : "green", "make" : "toyota", "sold" : "2014-08-19" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
{ "index": {}}
{ "price" : 80000, "color" : "red", "make" : "bmw", "sold" : "2014-01-01" }
{ "index": {}}
{ "price" : 25000, "color" : "blue", "make" : "ford", "sold" : "2014-02-12" }

有了数据,开始构建我们的第一个聚合。汽车经销商可能会想知道哪个颜色的汽车销量最好,用聚合可以轻易得到结果,用 terms 桶操作:

GET /cars/transactions/_search
{
    "size" : 0,
    "aggs" : { 
        "popular_colors" : { 
            "terms" : { 
              "field" : "color"
            }
        }
    }
}

聚合操作被置于顶层参数 aggs 之下(如果你愿意,完整形式 aggregations 同样有效)。

然后,可以为聚合指定一个我们想要名称,本例中是: popular_colors 。

最后,定义单个桶的类型 terms 。

聚合是在特定搜索结果背景下执行的, 这也就是说它只是查询请求的另外一个顶层参数(例如,使用 /_search 端点)。 聚合可以与查询结对,但我们会晚些在 限定聚合的范围(Scoping Aggregations) 中来解决这个问题。

注意

可能会注意到我们将 size 设置成 0 。我们并不关心搜索结果的具体内容,所以将返回记录数设置为 0 来提高查询速度。 设置 size: 0 与 Elasticsearch 1.x 中使用 count 搜索类型等价。

然后我们为聚合定义一个名字,名字的选择取决于使用者,响应的结果会以我们定义的名字为标签,这样应用就可以解析得到的结果。

随后我们定义聚合本身,在本例中,我们定义了一个单 terms 桶。 这个 terms 桶会为每个碰到的唯一词项动态创建新的桶。 因为我们告诉它使用 color 字段,所以 terms 桶会为每个颜色动态创建新桶。

让我们运行聚合并查看结果:

{
...
   "hits": {
      "hits": [] 
   },
   "aggregations": {
      "popular_colors": { 
         "buckets": [
            {
               "key": "red", 
               "doc_count": 4 
            },
            {
               "key": "blue",
               "doc_count": 2
            },
            {
               "key": "green",
               "doc_count": 2
            }
         ]
      }
   }
}

因为我们设置了 size 参数,所以不会有 hits 搜索结果返回。

popular_colors 聚合是作为 aggregations 字段的一部分被返回的。

每个桶的 key 都与 color 字段里找到的唯一词对应。它总会包含 doc_count 字段,告诉我们包含该词项的文档数量。

每个桶的数量代表该颜色的文档数量。

响应包含多个桶,每个对应一个唯一颜色(例如:红 或 绿)。每个桶也包括 聚合进 该桶的所有文档的数量。例如,有四辆红色的车。

前面的这个例子完全是实时执行的:一旦文档可以被搜到,它就能被聚合。这也就意味着我们可以直接将聚合的结果源源不断的传入图形库,然后生成实时的仪表盘。 不久,你又销售了一辆银色的车,我们的图形就会立即动态更新银色车的统计信息。

瞧!这就是我们的第一个聚合!

java代码实现:

①、实例化es

private static TransportClient client;
static {
	try {
		String esClusterName = "shopmall-es";
		List<String> clusterNodes = Arrays.asList("http://172.16.32.69:9300","http://172.16.32.48:9300");
		Settings settings = Settings.builder().put("cluster.name", esClusterName).build();
		client = new PreBuiltTransportClient(settings);
		for (String node : clusterNodes) {
			URI host = URI.create(node);
			client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host.getHost()), host.getPort()));
		}
	} catch (Exception e) {
		log.error("elasticsearchUtils init exception", e);
	}
}

public static void close() {
	client.close();
}
②、度量聚合实现

/**
      * Description:指标聚合查询,COUNT(color) ,min ,max,sum等相当于指标
      * 
      * @author wangweidong
      * CreateTime: 2017年11月9日 上午10:43:18
      * 
      * 数据格式:{ "price" : 10000, "color" : "red", "make" : "honda", "sold" : "2014-10-28" }
      * 
      * 1、可能会注意到我们将 size 设置成 0 。我们并不关心搜索结果的具体内容,所以将返回记录数设置为 0 来提高查询速度。 设置 size: 0 与 Elasticsearch 1.x 中使用 count 搜索类型等价。
      * 
      * 2、对text 字段上的脚本进行排序,聚合或访问值时,出现Fielddata is disabled on text fields by default. Set fielddata=true on [color] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory.
      *    Fielddata默认情况下禁用文本字段,因为Fielddata可以消耗大量的堆空间,特别是在加载高基数text字段时。一旦fielddata被加载到堆中,它将在该段的生命周期中保持在那里。此外,加载fielddata是一个昂贵的过程,可以导致用户体验延迟命中。
      *    可以使用使用该my_field.keyword字段进行聚合,排序或脚本或者启用fielddata(不建议使用)
     */
    @Test
    public void metricsAggregation() {
    	try {
    		String index = "cars";
        	String type = "transactions";
            
        	SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type);
//        	MaxAggregationBuilder field = AggregationBuilders.max("max_price").field("price");
        	//MinAggregationBuilder 统计最小值
//        	MinAggregationBuilder field = AggregationBuilders.min("min_price").field("price");
        	//SumAggregationBuilder 统计合计
//        	SumAggregationBuilder field = AggregationBuilders.sum("sum_price").field("price");
        	//StatsAggregationBuilder 统计聚合即一次性获取最小值、最小值、平均值、求和、统计聚合的集合。
        	StatsAggregationBuilder field = AggregationBuilders.stats("stats_price").field("price");
            searchRequestBuilder.addAggregation(field);
            searchRequestBuilder.setSize(0);
            SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
            
            System.out.println(searchResponse.toString());
            Aggregations agg = searchResponse.getAggregations();
            if(agg == null) {
            	return;
            }
            
//            Max max = agg.get("max_price");
//            System.out.println(max.getValue());
            
//            Min min = agg.get("min_price");
//            System.out.println(min.getValue());
            
//            Sum sum = agg.get("sum_price");
//            System.out.println(sum.getValue());
            
            Stats stats = agg.get("stats_price");
            System.out.println("最大值:"+stats.getMax());
            System.out.println("最小值:"+stats.getMin());
            System.out.println("平均值:"+stats.getAvg());
            System.out.println("合计:"+stats.getSum());
            System.out.println("总条数:"+stats.getCount());
            
		} catch (Exception e) {
			e.printStackTrace();
		}
    }

③、桶聚合实现

/**
     * Description:桶聚合查询,GROUP BY相当于桶
     * 
     * @author wangweidong
     * CreateTime: 2017年11月9日 下午3:47:54
     *
    */
   @Test
   public void bucketsAggregation() {
	   String index = "cars";
	   String type = "transactions";
	   SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type);
   	
       TermsAggregationBuilder field = AggregationBuilders.terms("popular_colors").field("color.keyword");
       searchRequestBuilder.addAggregation(field);
       searchRequestBuilder.setSize(0);
       SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
       
       System.out.println(searchResponse.toString());
       
       Terms genders = searchResponse.getAggregations().get("popular_colors");
	    for (Terms.Bucket entry : genders.getBuckets()) {
	    	Object key = entry.getKey();      // Term
	        Long count = entry.getDocCount(); // Doc count
	        
	        System.out.println(key);
	        System.out.println(count);
	    }
   }

文章参考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_aggregation_test_drive.html#_aggregation_test_drive


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值