ElasticSearch 1.5中的管道聚合

时间:2016-07-23 19:47:22

标签: elasticsearch querydsl

我想知道在同一个查询中是否有可能ES在其他聚合上运行聚合?

基本上,这称为流水线。

我正在谈论ElasticSearch 1.5,是的,我知道,这是不幸的,但我仍然坚持AWS这就是他们所做的事情。再卖,我必须忍受。

我猜这是不可能的,所以我马上写下问题的下一阶段。

假设我可以根据之前查询的结果多次查询ES,您将如何执行以下操作:

  1. 列出按文档中出现次数排序的前100个标签? (每个记录都有一个字段tags,我想知道哪些标记最常见) - 过去一小时

  2. 拥有100个标签中的每个标签;将出现次数除以1小时的分组(由Y 表示代表最后一小时的数字)。

  3. 然后,计算出多少百分比,Y偏离所有其他1小时水桶的平均值。

  4. 感谢您的帮助!!!

1 个答案:

答案 0 :(得分:1)

  

基本上,这称为流水线。

没有。直到Elasticsearch 2.0才出现Pipeline Aggregations。对于它的价值,Elastic确实提供了自己的ESaaS offering with Elastic Cloud。它也可以在AWS上运行。

  

......你将如何做以下

前两个更多地遵循范围的流程,而不是处理这些值。

{
  "query": {
    "filtered": {
      "filter": {
        "range" : {
          "timestamp": {
            "gte": "now-1h"
          }
        }
      }
    }
  }
}

这将为您提供最后一小时的数据。

{
  "size": 0,
  "aggs": {
    "group_by_tag": {
      "terms": {
        "field": "tag",
        "size": 100
      }
    }
  }
}

这将为您提供有史以来的前100个标签。

如果你把它们放在一起,那么你会在过去一小时内得到前100个标签。

对于第二个请求,听起来你想要混合使用,但你还想要的不仅仅是最后一个小时。

每当执行聚合(或GROUP BY查询)时,您需要考虑增量步骤。如果你想按小时分组,然后做一些事情,那就是它需要发生的顺序。所以它不是"现在我有最后一小时,让& #39; s得到其他时间"。一旦你缩小了窗口(范围),那么你就无法回头了。

因此,为了得到数字2,我们需要以不同的方式看待它。分组你想要多少小时(你想要多少1小时的桶),然后得到那些,然后得到每桶的计数。我会猜测并说你需要24小时1小时的水桶(注意24 * 100是2400,这不是无关紧要的!)。

那是很多桶,所以也许我们可以用不同的方式思考这个问题。

  1. 我想要前100名的最后一小时成绩。
  2. 我想要X时间的所有前100个平均 (你定义X的地方,减少它会使它更快,但自然限于选择窗口)。通过限制过滤器,我们减少了整体聚合的范围:
  3. 这可能如下所示:

    {
      "size": 0,
      "query": {
        "filtered": {
          "filter": {
            "range" : {
              "timestamp": {
                "gte": "now-24h"
              }
            }
          }
        }
      },
      "aggs": {
        "group_by_hour_and_day": {
          "date_range": {
            "field": "timestamp",
            "ranges": [
              { "from": "now-1h" },
              { "to": "now-1h" }
            ]
          },
          "aggs": {
            "group_by_tag": {
              "field": "tag",
              "size": 100
            }
          }
        }
      }
    }
    

    此请求的问题在于它会向您now-24 to now-1h,然后now-1hnow。你要求的东西非常宽松,但它并没有按期限给予它(可能或不重要)。相反,该术语由时间代替(再次,步骤/顺序事项)。然后,您可以说前24小时平均值是较宽窗口的响应文档计数除以窗口大小(在这种情况下为23小时为23)。如果您想要包含平均值中的最后一小时,则可以将"to": "now-1h"更改为"to": "now"

    我们或许可以通过翻转来给我们不同的答案,但需要更多的努力(查询仍然需要考虑最大时间范围):

    {
      "size": 0,
      "query": { ... },
      "aggs": {
        "group_by_tag": {
          "terms": {
            "field": "tag",
            "size": 100
          },
          "aggs": {
            "group_by_range": {
              "field": "timestamp",
              "ranges": [
                { "from": "now-1h" },
                { "to": "now-1h" }
              ]
            }
          }
        }
      }
    }
    

    请注意,现在我们首先在整个范围内按标记聚合。您可以删除第二个date_range聚合,因为您现在拥有时间窗口的总计。这种方法的问题在于,你可能在过去一小时内得到一个非常受欢迎的标签,在过去的整个范围内都不够流行,并且所以它不会出现在所有中。

    解决方案是通过进行两次顶级聚合来添加额外的步骤。一个是全范围的前100名,一个是前一个小时的前100名。

    {
      "size": 0,
      "query": { ... },
      "aggs": {
        "group_by_tag": {
          "terms": {
            "field": "tag",
            "size": 100
          }
        },
        "group_by_last_hour": {
          "filter": {
            "range": {
              "timestamp": {
                "gte": "now-1h"
              }
            }
          },
          "aggs": {
            "terms": {
              "field": "tag",
              "size": 100
            }
          }
        }
      }
    }
    

    这给出了完整窗口的前100名 - 无论可能是什么 - 然后它还分别给出了最后一小时的前100名。

      

    然后,计算多少百分比,Y偏离所有其他1小时水桶的平均值。

    根据您关注的任何形式在客户端执行此操作,并通过交叉比较计算平均值。

    考虑到查询的类型,您应该缓存结果,这样您就可以使用比其他方式更大的窗口大小。