Aggregations

尝试聚合

GET /cars/transactions/_search
{
    "size" : 0,
    "aggs" : { (1)
        "popular_colors" : { (2)
            "terms" : { (3)
              "field" : "color"
            }
        }
    }
}

结果:

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

添加度量指标

GET /cars/transactions/_search
{
   "size" : 0,
   "aggs": {
      "colors": {
         "terms": {
            "field": "color"
         },
         "aggs": { (1)
            "avg_price": { (2)
               "avg": {
                  "field": "price" (3)
               }
            }
         }
      }
   }
}

结果:

{
...
   "aggregations": {
      "colors": {
         "buckets": [
            {
               "key": "red",
               "doc_count": 4,
               "avg_price": { (1)
                  "value": 32500
               }
            },
            {
               "key": "blue",
               "doc_count": 2,
               "avg_price": {
                  "value": 20000
               }
            },
            {
               "key": "green",
               "doc_count": 2,
               "avg_price": {
                  "value": 21000
               }
            }
         ]
      }
   }
...
}

嵌套桶

GET /cars/transactions/_search
{
   "size" : 0,
   "aggs": {
      "colors": {
         "terms": {
            "field": "color"
         },
         "aggs": {
            "avg_price": { (1)
               "avg": {
                  "field": "price"
               }
            },
            "make": { (2)
                "terms": {
                    "field": "make" (3)
                }
            }
         }
      }
   }
}

结果:

{
...
   "aggregations": {
      "colors": {
         "buckets": [
            {
               "key": "red",
               "doc_count": 4,
               "make": { (1)
                  "buckets": [
                     {
                        "key": "honda", (2)
                        "doc_count": 3
                     },
                     {
                        "key": "bmw",
                        "doc_count": 1
                     }
                  ]
               },
               "avg_price": {
                  "value": 32500 (3)
               }
            },

...
}

告诉我们:
1、红色车有4量
2、红色车的平均售价32500
3、其中3辆是honda,1辆是bmw

最后的修改(为每个汽车厂商计算最低和最高的价格)

GET /cars/transactions/_search
{
   "size" : 0,
   "aggs": {
      "colors": {
         "terms": {
            "field": "color"
         },
         "aggs": {
            "avg_price": { "avg": { "field": "price" }
            },
            "make" : {
                "terms" : {
                    "field" : "make"
                },
                "aggs" : { (1)
                    "min_price" : { "min": { "field": "price"} }, (2)
                    "max_price" : { "max": { "field": "price"} } (3)
                }
            }
         }
      }
   }
}

结果:

{
...
   "aggregations": {
      "colors": {
         "buckets": [
            {
               "key": "red",
               "doc_count": 4,
               "make": {
                  "buckets": [
                     {
                        "key": "honda",
                        "doc_count": 3,
                        "min_price": {
                           "value": 10000 (1)
                        },
                        "max_price": {
                           "value": 20000 (1)
                        }
                     },
                     {
                        "key": "bmw",
                        "doc_count": 1,
                        "min_price": {
                           "value": 80000
                        },
                        "max_price": {
                           "value": 80000
                        }
                     }
                  ]
               },
               "avg_price": {
                  "value": 32500
               }
            },
...

告诉我们:
1、4辆红色车
2、红色车的平均售价是32500
3、3辆红色车是honda,1辆是bmw
4、最便宜的红色honda是10000
5、最贵的红色honda是20000

条形图

聚合能够被转换成图表和图形

{
   "size" : 0,
   "aggs":{
      "price":{
         "histogram":{ (1)
            "field": "price",
            "interval": 20000
         },
         "aggs":{
            "revenue": {
               "sum": { (2)
                 "field" : "price"
               }
             }
         }
      }
   }
}

1、直方图(条形图)histogram要求两个参数,一个数值字段以及一个定义桶大小间隔。
2、sum度量嵌套在每个售价区间内,用来显示每个区间内的总收入。

响应如下:

{
...
   "aggregations": {
      "price": {
         "buckets": [
            {
               "key": 0,
               "doc_count": 3,
               "revenue": {
                  "value": 37000
               }
            },
            {
               "key": 20000,
               "doc_count": 4,
               "revenue": {
                  "value": 95000
               }
            },
            {
               "key": 80000,
               "doc_count": 1,
               "revenue": {
                  "value": 80000
               }
            }
         ]
      }
   }
}

key:0代表0-19999,以此类推
当然,我们可以为任何聚合输出的分类和统计结果创建条形图,而不只是直方图。
最受欢迎10种汽车以及它们的平均售价、标准差这些信息

GET /cars/transactions/_search
{
  "size" : 0,
  "aggs": {
    "makes": {
      "terms": {
        "field": "make",
        "size": 10
      },
      "aggs": {
        "stats": {
          "extended_stats": {
            "field": "price"
          }
        }
      }
    }
  }
}

上述代码会按受欢迎度返回制造商列表以及它们各自的统计信息。
未给出响应,需要实验。

按时间统计

无论什么数据,只要带有时间戳,就可以进行data_histogram分析,在时间维度上构建指标分析。
date_histogram倾向于转换成线状图用以展示时间序列
histogram bucket是可以处理日期的,但是它不能自动识别日期。
date_histogram可以指定时间段、还能知道时间之间的关系,还能合理处理时区

GET /cars/transactions/_search
{
   "size" : 0,
   "aggs": {
      "sales": {
         "date_histogram": {
            "field": "sold",
            "interval": "month", (1)
            "format": "yyyy-MM-dd" (2)
         }
      }
   }
}

1、时间间隔
2、日期格式
响应结果如下所示,表示每月销售多少台汽车

{
   ...
   "aggregations": {
      "sales": {
         "buckets": [
            {
               "key_as_string": "2014-01-01",
               "key": 1388534400000,
               "doc_count": 1
            },
            {
               "key_as_string": "2014-02-01",
               "key": 1391212800000,
               "doc_count": 1
            },
            {
               "key_as_string": "2014-05-01",
               "key": 1398902400000,
               "doc_count": 1
            },
            {
               "key_as_string": "2014-07-01",
               "key": 1404172800000,
               "doc_count": 1
            },
            {
               "key_as_string": "2014-08-01",
               "key": 1406851200000,
               "doc_count": 1
            },
            {
               "key_as_string": "2014-10-01",
               "key": 1412121600000,
               "doc_count": 1
            },
            {
               "key_as_string": "2014-11-01",
               "key": 1414800000000,
               "doc_count": 2
            }
         ]
...
}

没有数据默认不返回。可以设置参数min_doc_count,强制返回buckets,即使buckets可能为空;extended_bounds,最大、最小日期范围

GET /cars/transactions/_search
{
   "size" : 0,
   "aggs": {
      "sales": {
         "date_histogram": {
            "field": "sold",
            "interval": "quarter", (1)
            "format": "yyyy-MM-dd",
            "min_doc_count" : 0,
            "extended_bounds" : {
                "min" : "2014-01-01",
                "max" : "2014-12-31"
            }
         },
         "aggs": {
            "per_make_sum": {
               "terms": {
                  "field": "make"
               },
               "aggs": {
                  "sum_price": {
                     "sum": { "field": "price" } (2)
                  }
               }
            },
            "total_sum": {
               "sum": { "field": "price" } (3)
            }
         }
      }
   }
}

1、每个季度
2、计算每种品牌的总销售金额
3、计算所有全部品牌的汇总销售金额
响应结果:

{
....
"aggregations": {
   "sales": {
      "buckets": [
         {
            "key_as_string": "2014-01-01",
            "key": 1388534400000,
            "doc_count": 2,
            "total_sum": {
               "value": 105000
            },
            "per_make_sum": {
               "buckets": [
                  {
                     "key": "bmw",
                     "doc_count": 1,
                     "sum_price": {
                        "value": 80000
                     }
                  },
                  {
                     "key": "ford",
                     "doc_count": 1,
                     "sum_price": {
                        "value": 25000
                     }
                  }
               ]
            }
         },
...
}

聚合表能做很多事情,例如kibana-用聚合构建的实时分析面板

范围限定的聚合

默认情况下,聚合是基于我们查询匹配的文档集合进行计算的。可以利用查询对聚合限定范围。

全局桶

通常我们希望聚合是在查询范围内的,但有时我们也想要搜索它的子集,而聚合的对象确实所有数据。
例如:

GET /cars/transactions/_search
{
    "size" : 0,
    "query" : {
        "match" : {
            "make" : "ford"
        }
    },
    "aggs" : {
        "single_avg_price": {
            "avg" : { "field" : "price" } (1)
        },
        "all": {
            "global" : {}, (2)
            "aggs" : {
                "avg_price": {
                    "avg" : { "field" : "price" } (3)
                }

            }
        }
    }
}

1、聚合操作在查询范围内
2、global全局桶没有参数
3、聚合操作针对所有文档,忽略汽车品牌

过滤和聚合

聚合范围限定还有一个自然的扩展就是过滤。因为聚合是在查询结果范围内操作的,任何可以适用于查询的过滤器也可以应用在聚合上。
例如:

GET /cars/transactions/_search
{
    "size" : 0,
    "query" : {
        "constant_score": {
            "filter": {
                "range": {
                    "price": {
                        "gte": 10000
                    }
                }
            }
        }
    },
    "aggs" : {
        "single_avg_price": {
            "avg" : { "field" : "price" }
        }
    }
}

过滤桶

如果我们只想对聚合结果过滤怎么办?
我们希望显示用户搜索的结果,也希望显示(与搜索匹配的)上个月度汽车的平均售价。

GET /cars/transactions/_search
{
   "size" : 0,
   "query":{
      "match": {
         "make": "ford"
      }
   },
   "aggs":{
      "recent_sales": {
         "filter": { (1)
            "range": {
               "sold": {
                  "from": "now-1M"
               }
            }
         },
         "aggs": {
            "average_price":{
               "avg": {
                  "field": "price" (2)
               }
            }
         }
      }
   }
}

1、使用过滤桶在查询范围基础上应用过滤器(当文档满足过滤桶条件时,加入到桶内)
2、avg度量智慧对ford并且是上个月售出的文档计算平均售价

后过滤器

只过滤搜索结果,不过滤聚合结果。可以使用post_filter。
它是接收一个过滤器的顶层搜索请求元素。这个过滤器在查询之后执行。
例如:

GET /cars/transactions/_search
{
    "size" : 0,
    "query": {
        "match": {
            "make": "ford"
        }
    },
    "post_filter": {    (1)
        "term" : {
            "color" : "green"
        }
    },
    "aggs" : {
        "all_colors": {
            "terms" : { "field" : "color" }
        }
    }
}

查询部分找到所有的ford汽车,然后用terms聚合创建一个颜色列表。
post_filter会过滤搜索结果,只展示绿色ford汽车。所以聚合不受影响。

多桶排序

多值桶(terms、histogram、date_histogram)动态生成很多桶。默认根据doc_count降序排列。有时我们需要修改这个顺序,不同的桶有着不同的处理方式。
1、内置排序

GET /cars/transactions/_search
{
    "size" : 0,
    "aggs" : {
        "colors" : {
            "terms" : {
              "field" : "color",
              "order": {
                "_count" : "asc" (1)
              }
            }
        }
    }
}

order对象,允许我们根据以下几个值中的一个值进行排序:
_count,按doc_count值排列,对terms、histogram、date_histogram有效
_term,按词项的字符串值的字母顺序排序。只在terms内使用
_key,按每个桶的键值数值排序,与_term类似,只在histogram和date_histogram内使用
2、按度量排序

GET /cars/transactions/_search
{
    "size" : 0,
    "aggs" : {
        "colors" : {
            "terms" : {
              "field" : "color",
              "order": {
                "avg_price" : "asc" (2)
              }
            },
            "aggs": {
                "avg_price": {
                    "avg": {"field": "price"} (1)
                }
            }
        }
    }
}

计算每个桶的平均售价、桶按照计算平均值的升序排序
多个度量值:使用.

GET /cars/transactions/_search
{
    "size" : 0,
    "aggs" : {
        "colors" : {
            "terms" : {
              "field" : "color",
              "order": {
                "stats.variance" : "asc" (1)
              }
            },
            "aggs": {
                "stats": {
                    "extended_stats": {"field": "price"}
                }
            }
        }
    }
}

3、基于“深度”度量排序
定义更深的路径,可以使用>,路径上的每个桶都必须是单值的。
目前只有三个单值桶filter、global、reverse_nested
创建一个汽车售价的直方图,但是按照红色和绿色(不包括蓝色)车各自的方差来排序:

GET /cars/transactions/_search
{
    "size" : 0,
    "aggs" : {
        "colors" : {
            "histogram" : {
              "field" : "price",
              "interval": 20000,
              "order": {
                "red_green_cars>stats.variance" : "asc" (1)
              }
            },
            "aggs": {
                "red_green_cars": {
                    "filter": { "terms": {"color": ["red", "green"]}}, (2)
                    "aggs": {
                        "stats": {"extended_stats": {"field" : "price"}} (3)
                    }
                }
            }
        }
    }
}

1.按照嵌套度量的方差对桶的直方图进行排序
2.因为我们你用单值过滤器,我们可以使用嵌套排序
3.按照生成的度量对统计结果进行排序。

近似聚合

有些算法可以分布执行,高度并行的,它们无须任何额外代价,就能在多台机器上并行执行。例如计算max
1、把请求广播到所有分片。
2、查看每个文档的price字段。如果price>current_max,则替换 。
3、返回所有分片的最大price并传给协调节点。
4、找到从所有分片返回的最大price。这是最终的最大值
这个算法随着机器的增长而横向扩展,无须任何协调操作(机器之间不需要讨论中间结果)
然而不是所有算法都如max这样简单。需要再算法的性能和内存使用上做出权衡。
三角因子模型:大数据、精确性和实时性。
我们需要选择其中两项:
精确+实时:数据存入单台机器的内存之中。
大数据+精确:例如hadoop。可以处理PB级的数据并且为我们提供精确的答案,但可能需要几周才能出结果。
大数据+实时:近似算法为我们提供准确但不精确的结果
ES支持两种近似算法cardinality和percentiles。

统计去重后的数量

cardinality:提供一个字段的基数,即该字段的distinct或者unique值的数目
经销商销售汽车颜色的数量:

GET /cars/transactions/_search
{
    "size" : 0,
    "aggs" : {
        "distinct_colors" : {
            "cardinality" : {
              "field" : "color"
            }
        }
    }
}

返回:

...
"aggregations": {
  "distinct_colors": {
     "value": 3
  }
}
...

每个月有多少颜色的车被售出

GET /cars/transactions/_search
{
  "size" : 0,
  "aggs" : {
      "months" : {
        "date_histogram": {
          "field": "sold",
          "interval": "month"
        },
        "aggs": {
          "distinct_colors" : {
              "cardinality" : {
                "field" : "color"
              }
          }
        }
      }
  }
}

cardinality度量是一个近似算法,基于HyperLogLog算法。
可配置的精度,更精确=更多内存
小的数据集精度非常高
可以固定内存使用量
可以通过参数precision_threshold(0-40000)配置精度
值在100以内时会得到非常准确的结果
HyperLogLog只是简单的对数据做哈希以及一些位操作。想进一步优化的话可以在索引时将字段内容的哈希值计算好

百分位计算

percentiles百分位数度量
使用一个TDigest算法,特性如下:
1、百分位的准确度与百分位的极端程度相关。1%或99%要比50%要准确
2、数据集合较小时,百分位非常准确
3、随着桶里数据的增长,算法会能准确度和内存节省之间做出权衡。

通过聚合发现异常指标

significant_terms分析统计你的数据并通过对比正常数据找到可能有异常频次的指标。
基于流程程度推荐
基于统计的推荐
Doc Values不是由JVM来管理,本质上是一个序列化的列式存储
Doc Values默认对所有字段启用,除了analyzed strings。所以我们可以选择对数据集里面的大多数字段进行聚合和排序操作。但是如果确定永远不会对某些字段进行聚合、排序或是脚本操作,可以禁用Doc Values,从而节省磁盘空间。

聚合与分析

fielddata数据结构,常驻于JVM内存堆中。(逐步淘汰)
not_analyzed字段,可以通过doc values节省内存
analyzed字段,使用fielddata并加载到内存中。是否有ngrams有一个非常大的基础,如果是,对内存来说极度不友好
fielddata熔断器、过滤、
预加载:预加载 fielddata、预加载全局序号、缓存预热

优化聚合查询

深度优先与广度优先,剪枝

你可能感兴趣的:(Aggregations)