ElasticSearch 2 (29) - 信息聚合系列之测试驱动
ElasticSearch 2 (29) - 信息聚合系列之测试驱动
摘要
我们可以用以下几页定义不同的聚合和它们的语法,但学习聚合的最佳途径就是用实例来说明。一旦我们获得了聚合的思想,以及如何合理地嵌套使用它们,那么语法就变得不那么重要。
版本
elasticsearch版本: elasticsearch-2.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" : { #1
"popular_colors" : { #2
"terms" : { #3
"field" : "color"
}
}
}
}
#1 聚合操作被至于顶层参数 aggs 之下(如果愿意也可以用完整形式 aggregations 同样有效)。
#2 然后,可以为聚合指定一个我们想要名称,本例中是:popular_colors。
#3 最后,定义单个桶的类型 terms。
聚合是在特定搜索结果背景下执行的,这也就是说它只是另外一个查询请求的顶层参数(例如,使用 /_search 端点)。聚合可以与查询结对,但我们会晚些在 限定聚合的范围(Scoping Aggregations) 中来解决这个问题。
注意
可能会注意到我们将 size 设置成 0 。我们并不关心搜索结果的具体内容,所以将返回记录数设置为 0 来提高查询速度。设置
size: 0与 Elasticsearch 1.x 中使用count类型等价。
然后我们为聚合定义一个名字,名字的选择取决于使用者,响应的结果会以我们定义的名字为标签,这样应用就可以解析得到的结果。
随后我们定义聚合本身,在本例中,我们定义了一个单 terms 桶,它会为每个碰到的唯一词项动态创建新的桶。因为我们告诉它使用 color 字段,所以它会为每个颜色动态创建新桶。
让我们运行聚合并查看结果:
{
...
"hits": {
"hits": [] #1
},
"aggregations": {
"colors": { #2
"buckets": [
{
"key": "red", #3
"doc_count": 4 #4
},
{
"key": "blue",
"doc_count": 2
},
{
"key": "green",
"doc_count": 2
}
]
}
}
}
#1 因为我们设置了 size 参数,所以不会有 hits 搜索结果返回。
#2 colors 聚合是作为 aggregations 字段的一部分被返回的。
#3 每个桶的键值都与 color 字段里找到的唯一词对应。它总会包含doc_count 字段,告诉我们包含该词项的文档数量。
#4 每个桶的数量代表该颜色的文档数量。
响应包含多个桶,每个对应一个唯一颜色(例如:红 或 绿)。每个桶也包括“掉入”该桶的所有文档的数量。例如,有四两红色的车。
前面的这个例子完全是实时执行的:一旦文档可以被搜到,它就能被聚合。这也就意味着我们可以直接将聚合的结果源源不断的传入图形库,然后生成实时的仪表盘。只要销售了一辆银色的车,我们的图形就会立即动态更新银色车的统计信息。
瞧!这就是我们的第一个聚合!
混合度量(Adding a Metric to the Mix)
前面的例子告诉我们每个桶里面的文档数量,这很有用。但通常,我们的应用需要提供更复杂的文档度量。例如,每种颜色汽车的平均价格是多少?
为了获取更多信息,我们需要告诉 Elasticsearch 使用哪个字段,计算何种度量。这需要将度量嵌套在桶内,度量会基于桶内的文档计算统计结果。
让我们继续为汽车的例子加入 average 平均度量:
GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"colors": {
"terms": {
"field": "color"
},
"aggs": { #1
"avg_price": { #2
"avg": {
"field": "price" #3
}
}
}
}
}
}
#1 为度量新增 aggs 层。
#2 为度量指定名字:avg_price。
#3 最后,为 price 字段定义 avg 度量。
正如所见,我们用前面的例子加入了新的 aggs 层。这个新的聚合层让我们可以将 avg 度量嵌套置于桶内。实际上,这就为每个颜色生成了平均价格。
正如颜色的例子,我们需要给度量起一个名字(avg_price),这样可以稍后根据名字获取它的值。最后,我们指定度量本身(avg)以及我们想要计算平均值的字段(price):
{
...
"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
}
}
]
}
}
...
}
#1 响应中的新元素 avg_price
尽管响应只发生很小改变,实际上我们获得的数据是增长了。之前,我们知道有四两红色的车,现在,红色车的平均价格是 $32,500 美元。这个信息可以直接显示在报表或者图形中。
桶中之桶(Buckets Inside Buckets)
在我们使用不同的嵌套方案时,聚合的力量才能真正得以显现。在前例中,我们以及看到如何将一个度量嵌入桶中,它的功能以及十分强大了。
但真正令人激动的分析来自于将桶嵌套进另外一个桶所能得到的结果。现在,我们想要找出每个汽车制造商生产出来汽车颜色的分布:
GET /cars/transactions/_search
{
"size" : 0,
"aggs": {
"colors": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": { #1
"avg": {
"field": "price"
}
},
"make": { #2
"terms": {
"field": "make" #3
}
}
}
}
}
}
#1 注意前例中的 avg_price 度量仍然保持原位。
#2 另一个聚合 make 被加入到了 color 颜色桶中。
#3 这个聚合是 terms 桶,它会为每个汽车生成唯一的桶。
这里发生了一些有趣的事,首先,我们可能会观察到之前例子中的 avg_price 度量完全没有变化,还在原来的位置。不同层级的聚合都可以有多个度量或桶,avg_price 度量告诉我们每种颜色汽车的平均价格。它与其他的桶和度量相互独立。
这对我们的应用非常重要,因为这里面有很多相互关联,但又完全不同的度量需要收集。聚合使我们能够用一次数据请求获得所有的这些信息。
另外一件值得注意的重要事情是我们新增的这个 make 聚合,它是一个 terms 桶(嵌套在 colors terms 颜色桶内),这意味着它会为数据集中的每个唯一组合生成 (color, make) 元组。
让我们看看返回的响应(为了简单我们只显示部分结果)
{
...
"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 正如期望的那样,新的聚合嵌入在每个颜色桶中。
#2 现在我们看见按不同制造商分解的每种颜色下车辆信息。
#3 最终,我们看到前例中的 avg_price 度量仍然维持不变。
响应结果告诉我们以下几点:
- 红色车有四辆。
- 红色车的平均售价是 $32,500 美元。
- 其中三辆是 Honda 本田制造,一辆是 BMW 宝马制造。
最后的修改(One Final Modification)
让我们回到话题的原点,在进入新话题之前,对我们的示例做最后一个修改,为每个汽车生成商计算最低和最高的价格:
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
}
}
}
}
}
}
#1 我们需要增加另外一个嵌套的 aggs 层级。
#2 然后包括 min 最小度量。
#3 以及 max 最大度量。
得到以下输出(只显示部分结果):
{
...
"aggregations": {
"colors": {
"buckets": [
{
"key": "red",
"doc_count": 4,
"make": {
"buckets": [
{
"key": "honda",
"doc_count": 3,
"min_price": {
"value": 10000 #1
},
"max_price": {
"value": 20000 #2
}
},
{
"key": "bmw",
"doc_count": 1,
"min_price": {
"value": 80000
},
"max_price": {
"value": 80000
}
}
]
},
"avg_price": {
"value": 32500
}
},
...
#1 #2 min 和 max 度量现在出现在每个汽车制造商下面。
有了这两个桶,我们可以对查询的结果进行扩展并得到以下信息:
- 有四辆红色车。
- 红色车的平均售价是 $32,500 美元。
- 其中三辆红色车是 Honda 本田制造,一辆是 BMW 宝马制造。
- 最便宜的红色本田售价为 $10,000 美元。
- 最贵的红色本田售价为 $20,000 美元。
参考
elastic.co:
Aggregation Test-Drive
ElasticSearch 2 (29) - 信息聚合系列之测试驱动的更多相关文章
- ElasticSearch 2 (37) - 信息聚合系列之内存与延时
ElasticSearch 2 (37) - 信息聚合系列之内存与延时 摘要 控制内存使用与延时 版本 elasticsearch版本: elasticsearch-2.x 内容 Fielddata ...
- ElasticSearch 2 (38) - 信息聚合系列之结束与思考
ElasticSearch 2 (38) - 信息聚合系列之结束与思考 摘要 版本 elasticsearch版本: elasticsearch-2.x 内容 本小节涵盖了许多基本理论以及很多深入的技 ...
- ElasticSearch 2 (36) - 信息聚合系列之显著项
ElasticSearch 2 (36) - 信息聚合系列之显著项 摘要 significant_terms(SigTerms)聚合与其他聚合都不相同.目前为止我们看到的所有聚合在本质上都是简单的数学 ...
- ElasticSearch 2 (35) - 信息聚合系列之近似聚合
ElasticSearch 2 (35) - 信息聚合系列之近似聚合 摘要 如果所有的数据都在一台机器上,那么生活会容易许多,CS201 课商教的经典算法就足够应付这些问题.但如果所有的数据都在一台机 ...
- ElasticSearch 2 (34) - 信息聚合系列之多值排序
ElasticSearch 2 (34) - 信息聚合系列之多值排序 摘要 多值桶(terms.histogram 和 date_histogram)动态生成很多桶,Elasticsearch 是如何 ...
- ElasticSearch 2 (33) - 信息聚合系列之聚合过滤
ElasticSearch 2 (33) - 信息聚合系列之聚合过滤 摘要 聚合范围限定还有一个自然的扩展就是过滤.因为聚合是在查询结果范围内操作的,任何可以适用于查询的过滤器也可以应用在聚合上. 版 ...
- ElasticSearch 2 (32) - 信息聚合系列之范围限定
ElasticSearch 2 (32) - 信息聚合系列之范围限定 摘要 到目前为止我们看到的所有聚合的例子都省略了搜索请求,完整的请求就是聚合本身. 聚合与搜索请求同时执行,但是我们需要理解一个新 ...
- ElasticSearch 2 (31) - 信息聚合系列之时间处理
ElasticSearch 2 (31) - 信息聚合系列之时间处理 摘要 如果说搜索是 Elasticsearch 里最受欢迎的功能,那么按时间创建直方图一定排在第二位.为什么需要使用时间直方图? ...
- ElasticSearch 2 (30) - 信息聚合系列之条形图
ElasticSearch 2 (30) - 信息聚合系列之条形图 摘要 版本 elasticsearch版本: elasticsearch-2.x 内容 聚合还有一个令人激动的特性就是能够十分容易地 ...
随机推荐
- [2018-12-15] Hello World!
这个blog以后就用来发oi相关的算法与数据结构了 还可能想学习一点web前端的知识和一些与计算机有关的软件和技术 可能有空大概会试试搭建blog以及一些各种软件和c++以外的玩意
- [Usaco2007 Jan]Balanced Lineup
嘟嘟嘟 一道RMQ板子题,分别维护最大值和最小值,不解释. #include<cstdio> #include<iostream> #include<algorithm& ...
- MyBatis之Collection
Collection翻译过来,意为"集合"的意思,既然是集合,肯定是代表多个. MyBatis以其自身,小巧易懂,闻名于JavaEE. 传统的JDBC就不说了,Hibernate记 ...
- dubbo接口访问控制
微服务背景下,一个web应用都可能不再service依赖,而是通过RPC调用远端服务器上的服务.这些服务里,就包括了一些不能轻易暴露的后台功能接口.暴露出去的dubbo接口注册到某一个zk上后,该du ...
- Qt Creator无法debug,报错:The selected debugger may be inappropriate for the inferior. Examining symbols and setting breakpoints by file name and line number may fail. The inferior is in the Portable ...
看到这个报错我是绝望的 解决:下载windows sdk win10 sdk 只安装Debugging Tools for Windows 打开 工具-选项-Kits 安装sdk成功后我们可以看到 ...
- Android 一个相对完整的自动升级功能实现代码
由于项目的需要最近做了一个关于Android自动升级的功能,下面将贴出Android手机客户端的完整代码.这段代码参考别的代码居多,由于不满足需求,所以自己仅仅改了一些需要变动的内容,其他功能都是按照 ...
- memset()初始化为1的那些事
问题代码: #include <stdio.h> #include <string.h> int main() { ]; int a; while(~scanf("% ...
- HDU 2059 龟兔赛跑(超级经典的线性DP,找合适的j,使得每个i的状态都是最好的)
龟兔赛跑 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status ...
- 在mvc视图中实现rdlc报表展示
需求:在view视图页面中嵌入rdlc报表,rdlc的xml为动态传入的xml字符串.本项目是基于abp框架 可能出现问题: 1.rdlc报表是由asp.net的服务器控件ReportViewer来支 ...
- 微信小程序开发 [06] 一些补充的知识点
0.写在前面的话 前几章的内容串联起来,基本上已经能写比较基础的小程序页面逻辑了,当然,wxml和wxss的我并没有写,因为前端我也并不擅长.这个章节,准备随便叨叨,然后补充一些之前没有提到的基础知识 ...