Bucket Aggregation 桶聚合 ---------group by (上)

Global Aggregation

全局聚合,最顶级的聚合,无法嵌入到其他bucket聚合+

example:

POST /sales/_search?size=0
{
    "query" : {
        "match" : { "type" : "t-shirt" }
    },
    "aggs" : {
        "all_products" : {
            "global" : {}, 
            "aggs" : { 
                "avg_price" : { "avg" : { "field" : "price" } }
            }
        },
        "t_shirts": { "avg" : { "field" : "price" } }
    }
}

result:

{
    ...
    "aggregations" : {
        "all_products" : {
            "doc_count" : 7, 
            "avg_price" : {
                "value" : 140.71428571428572 
            }
        },
        "t_shirts": {
            "value" : 128.33333333333334 
        }
    }
}

分析:global 查询了上下文 所有文档的 平均价格。avg_price 是为global 注册的聚合。

javaApi:

    1. 创建聚合请求

AggregationBuilders
    .global("agg")
    .subAggregation(AggregationBuilders.terms("genders").field("gender"));

    2.分析结果

// sr is here your SearchResponse object
Global agg = sr.getAggregations().get("agg");
agg.getDocCount(); // Doc count

Filter Aggregation

定义当前文档集上下文中与指定筛选器匹配的所有文档的单个桶。通常,这将用于将当前聚合上下文缩小到特定的一组文档。

简而言之 ,就是先查,再根据查到的再聚合。

example:

POST /sales/_search?size=0
{
    "aggs" : {
        "t_shirts" : {
            "filter" : { "term": { "type": "t-shirt" } },
            "aggs" : {
                "avg_price" : { "avg" : { "field" : "price" } }
            }
        }
    }
}
{
    ...
    "aggregations" : {
        "t_shirts" : {
            "doc_count" : 3,
            "avg_price" : { "value" : 128.33333333333334 }
        }
    }
}

分析:我们计算了所有t恤类型产品的平均价格。

javaapi:

AggregationBuilders
    .filter("agg", QueryBuilders.termQuery("gender", "male"));

Filters Aggregation

定义一个多桶聚合,其中每个桶与一个过滤器关联。每个bucket将收集与其关联的过滤器匹配的所有文档。

简而言之,先构建多个过滤器,再根据这些过滤器聚合。应用场景,如果你group by 后面的条件不仅仅是字段,而需要将字段中的各个值,重新分类,定义成不同的类型再group by,可以用这个聚合。

example

PUT /logs/message/_bulk?refresh
{ "index" : { "_id" : 1 } }
{ "body" : "warning: page could not be rendered" }
{ "index" : { "_id" : 2 } }
{ "body" : "authentication error" }
{ "index" : { "_id" : 3 } }
{ "body" : "warning: connection timed out" }

GET logs/_search
{
  "size": 0,
  "aggs" : {
    "messages" : {
      "filters" : {
        "filters" : {
          "errors" :   { "match" : { "body" : "error"   }},
          "warnings" : { "match" : { "body" : "warning" }}
        }
      }
    }
  }
}
{
  "took": 9,
  "timed_out": false,
  "_shards": ...,
  "hits": ...,
  "aggregations": {
    "messages": {
      "buckets": {
        "errors": {
          "doc_count": 1
        },
        "warnings": {
          "doc_count": 2
        }
      }
    }
  }
}

javaapi:

      request:

AggregationBuilder aggregation =
    AggregationBuilders
        .filters("agg",
            new FiltersAggregator.KeyedFilter("men", QueryBuilders.termQuery("gender", "male")),
            new FiltersAggregator.KeyedFilter("women", QueryBuilders.termQuery("gender", "female")));

    response:

// sr is here your SearchResponse object
Filters agg = sr.getAggregations().get("agg");

// For each entry
for (Filters.Bucket entry : agg.getBuckets()) {
    String key = entry.getKeyAsString();            // bucket key
    long docCount = entry.getDocCount();            // Doc count
    logger.info("key [{}], doc_count [{}]", key, docCount);
}

 

anonymous filters 匿名 

详情见官方文档,就是filter字段可以用过滤器数组,不需要对过滤器命名

other bucket

可以将other_bucket参数设置为向响应添加一个bucket,该响应将包含与任何给定过滤器不匹配的所有文档。

PUT logs/message/4?refresh
{
  "body": "info: user Bob logged out"
}

GET logs/_search
{
  "size": 0,
  "aggs" : {
    "messages" : {
      "filters" : {
        "other_bucket_key": "other_messages",
        "filters" : {
          "errors" :   { "match" : { "body" : "error"   }},
          "warnings" : { "match" : { "body" : "warning" }}
        }
      }
    }
  }
}
{
  "took": 3,
  "timed_out": false,
  "_shards": ...,
  "hits": ...,
  "aggregations": {
    "messages": {
      "buckets": {
        "errors": {
          "doc_count": 1
        },
        "warnings": {
          "doc_count": 2
        },
        "other_messages": {
          "doc_count": 1
        }
      }
    }
  }
}

Missing Aggregation 缺省聚合

一个基于字段数据的单桶聚合,它为当前文档集   中缺少字段值  的所有文档创建一个桶(实际上,缺少字段 或具有已配置的  空值集)。此聚合器通常 与其他字段 数据桶聚合器(例如范围)一起使用,以返回由于缺少字段数据值 而无法放在任何其他桶中  的所有文档的信息。简而言之,就是可以将 为空值的数据 放到一个桶中。

POST /sales/_search?size=0
{
    "aggs" : {
        "products_without_a_price" : {
            "missing" : { "field" : "price" }
        }
    }
}
{
    ...
    "aggregations" : {
        "products_without_a_price" : {
            "doc_count" : 00
        }
    }
}

获得没有价格的产品总数,为0很正常,产品怎么会没价格。

javaapi:

AggregationBuilders.missing("agg").field("gender");

分析结果,同上。

Nested Aggregation 嵌套聚合

一种特殊的单桶聚合,支持聚合嵌套文档。
例如,假设我们有一个产品索引,每个产品都包含分销商列表——每个分销商都有自己的产品价格。映射可以是这样的:

PUT /index
{
  "mappings": {
    "product" : {
        "properties" : {
            "resellers" : { 
                "type" : "nested",
                "properties" : {
                    "name" : { "type" : "text" },
                    "price" : { "type" : "double" }
                }
            }
        }
    }
  }
}
GET /_search
{
    "query" : {
        "match" : { "name" : "led tv" }
    },
    "aggs" : {
        "resellers" : {
            "nested" : {
                "path" : "resellers"
            },
            "aggs" : {
                "min_price" : { "min" : { "field" : "resellers.price" } }
            }
        }
    }
}
{
  ...
  "aggregations": {
    "resellers": {
      "doc_count": 0,
      "min_price": {
        "value": 350
      }
    }
  }
}

正如您在上面看到的,嵌套聚合需要顶层文档中的嵌套文档的路径。然后可以在这些嵌套文档上定义任何类型的聚合。

聚合将返回可以购买产品的最低价格

javaapi:

AggregationBuilders
    .nested("agg", "resellers");

分析结果同上。

预知后事如何,请看下篇。

官方英文文档:文档

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章