ElasticSearch Aggregation(七)

ElasticSearch Aggregation(七)

管道聚合

管道聚合作用于其他聚合后的结果上,而不是作用于文档集合。有很多不同类型的管道聚合,每一种都会根据其他聚合数据计算出不同的信息,但是这些类型可以分为两种家族:

  • Parent:一系列管道聚合,随其父聚合的输出一起提供,并且能够计算新存储桶或新聚合以添加到现有存储桶。
  • Sibling:管道聚合随同级聚合的输出一起提供,并且能够计算与同级聚合处于同一级别的新聚合。

管道聚合通过bucket_path参数来指定所需聚合的路径。定义bucket_path参数可以通过bucket_path语法来定义

管道聚合不能有子聚合,但根据类型,它可以引用 buckets_path 中的另一个管道,允许链接管道聚合。

提示:由于管道聚合仅添加到输出,因此在链接管道聚合时,每个管道聚合的输出将包含在最终输出中。

bucket_path语法

大多数管道聚合要求其他的聚合作为他的输入。输入的定义通过bucket_path参数来定义,可以根据以下格式来定义bucket_path参数:

AGG_SEPARATOR       =  `>` ;
METRIC_SEPARATOR    =  `.` ;
AGG_NAME            =  <the name of the aggregation> ;
METRIC              =  <the name of the metric (in case of multi-value metrics aggregation)> ;
MULTIBUCKET_KEY     =  `[<KEY_NAME>]`
PATH                =  <AGG_NAME><MULTIBUCKET_KEY>? (<AGG_SEPARATOR>, <AGG_NAME> )* ( <METRIC_SEPARATOR>, <METRIC> ) ;

例如,路径my_bucket>my_stats.avg将指向my_stats指标中的avg聚合值,该指标将会包含在my_bucket桶聚合中。

管道聚合的路径是相对的,不是绝对路径。例如移动平均数被嵌入到日期直方图的内部,并且引用一个兄弟指标the_sum

curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "aggs": {
    "my_date_histo": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      },
      "aggs": {
        "the_sum": {
          "sum": { "field": "lemmings" } 
        },
        "the_movavg": {
          "moving_avg": { "buckets_path": "the_sum" } 
        }
      }
    }
  }
}
'

以上例子目的是在每个聚合桶中对the_sum指标进行moving avg操作。

bucket_path也可以在兄弟管道聚合中使用。

curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "aggs": {
    "sales_per_month": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "sales": {
          "sum": {
            "field": "price"
          }
        }
      }
    },
    "max_monthly_sales": {
      "max_bucket": {
        "buckets_path": "sales_per_month>sales" 
      }
    }
  }
}
'

bucket_path指示在date_per_month数据直方图中后去sales聚合的最大值。

如果兄弟管道聚合引用了一个多桶聚合,例如terms聚合,可以在多桶中选择特定的键。例如bucket_script可以选择特定的桶执行计算:

curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "aggs": {
    "sales_per_month": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "sale_type": {
          "terms": {
            "field": "type"
          },
          "aggs": {
            "sales": {
              "sum": {
                "field": "price"
              }
            }
          }
        },
        "hat_vs_bag_ratio": {
          "bucket_script": {
            "buckets_path": {
              "hats": "sale_type['hat']>sales",   
              "bags": "sale_type['bag']>sales"    
            },
            "script": "params.hats / params.bags"
          }
        }
      }
    }
  }
}
'

特殊的路径

buckets_path可以使用一个特殊的_count路径,而不是一个指标路径。这意味着管道聚合使用文档数量作为其输入。例如,移动平均数可以根据每个桶的文档数量来计算,而不是一个特定的指标:

curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "aggs": {
    "my_date_histo": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      },
      "aggs": {
        "the_movavg": {
          "moving_avg": { "buckets_path": "_count" } 
        }
      }
    }
  }
}
'

average bucket聚合

平均桶聚合。同级管道聚合,用于计算同级聚合中指定指标的平均值。指定的指标必须是数字,同级聚合必须是多桶聚合。

语法
"avg_bucket": {
  "buckets_path": "sales_per_month>sales",
  "gap_policy": "skip",
  "format": "#,##0.00;(#,##0.00)"
}
参数
  • bucket_path:(必须,String),平均计算所需的桶路径
  • gep_policy:(可选,string),在数据中发现间距对应的处理策略。默认为skip
  • format:(可选的,String),输出的DecimalFormat模式的值。如果指定,将会在聚合的value_as_string属性中返回被格式化的值。
响应体
  • value:(flat),bucket_path指定的路径指标的平均值
  • value_as_string:(string),聚合的格式化输出值。只有在请求中指定了格式时才提供此属性。
例子

根据avg_monthly_sales聚合使用avg_bucket来计算每个月sales的平均值

curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "sales_per_month": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "sales": {
          "sum": {
            "field": "price"
          }
        }
      }
    },
    "avg_monthly_sales": {             
      "avg_bucket": {
        "buckets_path": "sales_per_month>sales",
        "gap_policy": "skip",
        "format": "#,##0.00;(#,##0.00)"
      }             
    }
  }
}
'

响应:

{
  "took": 11,
  "timed_out": false,
  "_shards": ...,
  "hits": ...,
  "aggregations": {
    "sales_per_month": {
      "buckets": [
        {
          "key_as_string": "2015/01/01 00:00:00",
          "key": 1420070400000,
          "doc_count": 3,
          "sales": {
            "value": 550.0
          }
        },
        {
          "key_as_string": "2015/02/01 00:00:00",
          "key": 1422748800000,
          "doc_count": 2,
          "sales": {
            "value": 60.0
          }
        },
        {
          "key_as_string": "2015/03/01 00:00:00",
          "key": 1425168000000,
          "doc_count": 2,
          "sales": {
            "value": 375.0
          }
        }
      ]
    },
    "avg_monthly_sales": {
      "value": 328.33333333333333,
      "value_as_string": "328.33"
    }
  }
}

bucket script聚合

可以执行脚本的父管道聚合,这个脚本可以在每个桶中单独执行。

语法
{
  "bucket_script": {
    "buckets_path": {
      "my_var1": "the_sum",                     
      "my_var2": "the_value_count"
    },
    "script": "params.my_var1 / params.my_var2"
  }
}

以下代码段计算了 T 恤销售额与每月总销售额的比率百分比:

curl -X POST "localhost:9200/sales/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "sales_per_month": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "total_sales": {
          "sum": {
            "field": "price"
          }
        },
        "t-shirts": {
          "filter": {
            "term": {
              "type": "t-shirt"
            }
          },
          "aggs": {
            "sales": {
              "sum": {
                "field": "price"
              }
            }
          }
        },
        "t-shirt-percentage": {
          "bucket_script": {
            "buckets_path": {
              "tShirtSales": "t-shirts>sales",
              "totalSales": "total_sales"
            },
            "script": "params.tShirtSales / params.totalSales * 100"
          }
        }
      }
    }
  }
}
'

响应:

{
   "took": 11,
   "timed_out": false,
   "_shards": ...,
   "hits": ...,
   "aggregations": {
      "sales_per_month": {
         "buckets": [
            {
               "key_as_string": "2015/01/01 00:00:00",
               "key": 1420070400000,
               "doc_count": 3,
               "total_sales": {
                   "value": 550.0
               },
               "t-shirts": {
                   "doc_count": 1,
                   "sales": {
                       "value": 200.0
                   }
               },
               "t-shirt-percentage": {
                   "value": 36.36363636363637
               }
            },
            {
               "key_as_string": "2015/02/01 00:00:00",
               "key": 1422748800000,
               "doc_count": 2,
               "total_sales": {
                   "value": 60.0
               },
               "t-shirts": {
                   "doc_count": 1,
                   "sales": {
                       "value": 10.0
                   }
               },
               "t-shirt-percentage": {
                   "value": 16.666666666666664
               }
            },
            {
               "key_as_string": "2015/03/01 00:00:00",
               "key": 1425168000000,
               "doc_count": 2,
               "total_sales": {
                   "value": 375.0
               },
               "t-shirts": {
                   "doc_count": 1,
                   "sales": {
                       "value": 175.0
                   }
               },
               "t-shirt-percentage": {
                   "value": 46.666666666666664
               }
            }
         ]
      }
   }
}

bucket selector聚合

执行脚本的父管道聚合,该脚本确定当前存储桶是否将保留在父多存储桶聚合中。指定的指标必须是数字,并且脚本必须返回布尔值。如果脚本语言是表达式,则允许使用数字返回值。在这种情况下,0.0将被计算为false,而所有其他值将被计算为true

提示:与所有管道聚合一样,bucket_selector聚合在所有其他同级聚合之后执行。这意味着使用bucket_selector聚合来过滤响应中返回的桶并不会节省运行聚合的执行时间。

语法
{
  "bucket_selector": {
    "buckets_path": {
      "my_var1": "the_sum",                     
      "my_var2": "the_value_count"
    },
    "script": "params.my_var1 > params.my_var2"
  }
}

以下代码段仅保留当月总销售额超过 200 的存储桶:

curl -X POST "localhost:9200/sales/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "sales_per_month": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "total_sales": {
          "sum": {
            "field": "price"
          }
        },
        "sales_bucket_filter": {
          "bucket_selector": {
            "buckets_path": {
              "totalSales": "total_sales"
            },
            "script": "params.totalSales > 200"
          }
        }
      }
    }
  }
}
'

响应:

{
   "took": 11,
   "timed_out": false,
   "_shards": ...,
   "hits": ...,
   "aggregations": {
      "sales_per_month": {
         "buckets": [
            {
               "key_as_string": "2015/01/01 00:00:00",
               "key": 1420070400000,
               "doc_count": 3,
               "total_sales": {
                   "value": 550.0
               }
            },
            {
               "key_as_string": "2015/03/01 00:00:00",
               "key": 1425168000000,
               "doc_count": 2,
               "total_sales": {
                   "value": 375.0
               },
            }
         ]
      }
   }
}

bucket sort聚合

父管道聚合,这聚合对父多桶聚合的结果进行排序。可以指定0个或者多个字段进行排序。每一个桶可能根据_key或者_count或者子聚合进行排序。此外,可以设置参数 fromsize 以截断结果桶。

提示:与所有管道聚合一样,bucket_sort 聚合在所有其他非管道聚合之后执行。这意味着排序仅适用于已从父聚合返回的任何桶。例如,如果父聚合是 term 并且其大小设置为 10,bucket_sort 将仅对这 10 个返回的 term 桶进行排序。

语法

bucket_sort 聚合如下所示:

{
  "bucket_sort": {
    "sort": [
      { "sort_field_1": { "order": "asc" } },   
      { "sort_field_2": { "order": "desc" } },
      "sort_field_3"
    ],
    "from": 1,
    "size": 3
  }
}

下面的代码片段按降序返回总销售额最高的3个月对应的桶:

curl -X POST "localhost:9200/sales/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "sales_per_month": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "total_sales": {
          "sum": {
            "field": "price"
          }
        },
        "sales_bucket_sort": {
          "bucket_sort": {
            "sort": [
              { "total_sales": { "order": "desc" } } 
            ],
            "size": 3                                
          }
        }
      }
    }
  }
}
'

响应:

{
   "took": 82,
   "timed_out": false,
   "_shards": ...,
   "hits": ...,
   "aggregations": {
      "sales_per_month": {
         "buckets": [
            {
               "key_as_string": "2015/01/01 00:00:00",
               "key": 1420070400000,
               "doc_count": 3,
               "total_sales": {
                   "value": 550.0
               }
            },
            {
               "key_as_string": "2015/03/01 00:00:00",
               "key": 1425168000000,
               "doc_count": 2,
               "total_sales": {
                   "value": 375.0
               },
            },
            {
               "key_as_string": "2015/02/01 00:00:00",
               "key": 1422748800000,
               "doc_count": 2,
               "total_sales": {
                   "value": 60.0
               },
            }
         ]
      }
   }
}
截断而不进行排序

你可能使用这个聚合来截断结果桶而不进行任何排序。为此你只需要设置fromsize参数,而不设置sort参数就可以达到这个效果

curl -X POST "localhost:9200/sales/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "sales_per_month": {
      "date_histogram": {
        "field": "date",
        "calendar_interval": "month"
      },
      "aggs": {
        "bucket_truncate": {
          "bucket_sort": {
            "from": 1,
            "size": 1
          }
        }
      }
    }
  }
}
'

响应:

{
   "took": 11,
   "timed_out": false,
   "_shards": ...,
   "hits": ...,
   "aggregations": {
      "sales_per_month": {
         "buckets": [
            {
               "key_as_string": "2015/02/01 00:00:00",
               "key": 1422748800000,
               "doc_count": 2
            }
         ]
      }
   }
}

cumulative cardinality聚合

累积基数聚合。累积基数聚合是一个父管道聚合,该聚合在父直方图聚合中计算累积基数。指定的指标必须是一个基数聚合并且外围的直方图必须设置min_doc_count0

cumulative_cardinality聚合对于发现总的新条目非常有用,可以理解为每天新访问你web网站的用户数量。常规的基数聚合只会告诉你每天有多少个唯一的访问用户,但是他不会区分新用户或者重复用户。累积基数聚合可用于确定每天有多少独立访问者是“新”访问者。

语法

cumulative_cardinality 聚合看起来像这样:

{
  "cumulative_cardinality": {
    "buckets_path": "my_cardinality_agg"
  }
}

以下代码段计算每日总用户的累积基数:

curl -X GET "localhost:9200/user_hits/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "users_per_day": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      },
      "aggs": {
        "distinct_users": {
          "cardinality": {
            "field": "user_id"
          }
        },
        "total_new_users": {
          "cumulative_cardinality": {
            "buckets_path": "distinct_users" 
          }
        }
      }
    }
  }
}
'

以下可能是响应:

{
   "took": 11,
   "timed_out": false,
   "_shards": ...,
   "hits": ...,
   "aggregations": {
      "users_per_day": {
         "buckets": [
            {
               "key_as_string": "2019-01-01T00:00:00.000Z",
               "key": 1546300800000,
               "doc_count": 2,
               "distinct_users": {
                  "value": 2
               },
               "total_new_users": {
                  "value": 2
               }
            },
            {
               "key_as_string": "2019-01-02T00:00:00.000Z",
               "key": 1546387200000,
               "doc_count": 2,
               "distinct_users": {
                  "value": 2
               },
               "total_new_users": {
                  "value": 3
               }
            },
            {
               "key_as_string": "2019-01-03T00:00:00.000Z",
               "key": 1546473600000,
               "doc_count": 3,
               "distinct_users": {
                  "value": 3
               },
               "total_new_users": {
                  "value": 4
               }
            }
         ]
      }
   }
}

注意第二天,2019-01-02,有两个不同的用户,但是累积管道agg生成的total_new_users指标只增加到3。这意味着当天的两个用户中只有一个是新用户,另一个在前一天已经被看到过。这种情况会在第三天再次发生,即三个用户中只有一个是全新的。

增量累积基数聚合

cumulative_cardinality 聚合将向您显示查询时间段开始以来的总数、不同的计数。然而,有时查看“增量”数量是有用的。意思是每天新增多少用户,而不是累计总数。

这可以通过向我们的查询添加derivative聚合来实现:

curl -X GET "localhost:9200/user_hits/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "users_per_day": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      },
      "aggs": {
        "distinct_users": {
          "cardinality": {
            "field": "user_id"
          }
        },
        "total_new_users": {
          "cumulative_cardinality": {
            "buckets_path": "distinct_users"
          }
        },
        "incremental_new_users": {
          "derivative": {
            "buckets_path": "total_new_users"
          }
        }
      }
    }
  }
}
'

以下可能是响应:

{
   "took": 11,
   "timed_out": false,
   "_shards": ...,
   "hits": ...,
   "aggregations": {
      "users_per_day": {
         "buckets": [
            {
               "key_as_string": "2019-01-01T00:00:00.000Z",
               "key": 1546300800000,
               "doc_count": 2,
               "distinct_users": {
                  "value": 2
               },
               "total_new_users": {
                  "value": 2
               }
            },
            {
               "key_as_string": "2019-01-02T00:00:00.000Z",
               "key": 1546387200000,
               "doc_count": 2,
               "distinct_users": {
                  "value": 2
               },
               "total_new_users": {
                  "value": 3
               },
               "incremental_new_users": {
                  "value": 1.0
               }
            },
            {
               "key_as_string": "2019-01-03T00:00:00.000Z",
               "key": 1546473600000,
               "doc_count": 3,
               "distinct_users": {
                  "value": 3
               },
               "total_new_users": {
                  "value": 4
               },
               "incremental_new_users": {
                  "value": 1.0
               }
            }
         ]
      }
   }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值