【问题标题】:How to perform a pipeline aggregation without returning all buckets in Elasticsearch如何在不返回 Elasticsearch 中的所有存储桶的情况下执行管道聚合
【发布时间】:2016-10-31 02:34:37
【问题描述】:

我正在使用 Elasticsearch 2.3,并且正在尝试使用管道聚合执行两步计算。 我只对管道聚合的最终结果感兴趣,但 Elasticsearch 会返回所有存储桶信息。

由于我有大量的存储桶(数千万或数亿),这是令人望而却步的。不幸的是,我找不到方法告诉 Es 不要返回所有这些信息。

这是一个玩具示例。我有一个索引test-index,文档类型为obj。 obj 有两个字段,key 和 values。

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{
  "value": 100,
  "key": "foo"
}'

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{
  "value": 20,
  "key": "foo"
}'

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{
  "value": 50,
  "key": "bar"
}'

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{
  "value": 60,
  "key": "bar"
}'

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{
  "value": 70,
  "key": "bar"
}'

我想获得具有相同keys 的objs 的最小值value 的平均值(在所有keys 上)。 最小值的平均值。

Elasticsearch 允许我这样做:

curl -XPOST 'http://10.10.0.7:9200/test-index/obj/_search' -d '{
  "size": 0,
  "query": {
    "match_all": {}
  },
  "aggregations": {
    "key_aggregates": {
      "terms": {
        "field": "key",
        "size": 0
      },
      "aggs": {
        "min_value": {
          "min": {
            "field": "value"
          }
        }
      }
    },
    "avg_min_value": {
      "avg_bucket": {
        "buckets_path": "key_aggregates>min_value"
      }
    }
  }
}'

但是这个查询返回每个桶的最小值,虽然我不需要它:

{
  "took": 21,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 0,
    "hits": [

    ]
  },
  "aggregations": {
    "key_aggregates": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "bar",
          "doc_count": 2,
          "min_value": {
            "value": 50
          }
        },
        {
          "key": "foo",
          "doc_count": 2,
          "min_value": {
            "value": 20
          }
        }
      ]
    },
    "avg_min_value": {
      "value": 35
    }
  }
}

有没有办法把"buckets": [...]里面的所有信息都去掉?我只对avg_min_value感兴趣。

在这个玩具示例中这似乎不是问题,但是当不同的keys 的数量不大(数千万或数亿)时,查询响应大得令人望而却步,我想对其进行修剪.

有没有办法用 Elasticsearch 做到这一点?还是我的数据建模错误?

注意:预先聚合每个键的数据是不可接受的,因为我的查询的 match_all 部分可能会被复杂且未知的过滤器替换。

NB2:在我的 terms 聚合中将 size 更改为非负数是不可接受的,因为它会改变结果。

【问题讨论】:

    标签: elasticsearch elasticsearch-aggregation


    【解决方案1】:

    我遇到了同样的问题,经过大量研究后,我找到了解决方案,并想在这里分享。

    您可以使用Response Filtering 功能过滤您希望收到的部分答案。

    您应该能够通过将查询参数filter_path=aggregations.avg_min_value 添加到搜索 URL 来实现您想要的。在示例情况下,它应该类似于:

    curl -XPOST 'http://10.10.0.7:9200/test-index/obj/_search?filter_path=aggregations.avg_min_value' -d '{
      "size": 0,
      "query": {
        "match_all": {}
      },
      "aggregations": {
        "key_aggregates": {
          "terms": {
            "field": "key",
            "size": 0
          },
          "aggs": {
            "min_value": {
              "min": {
                "field": "value"
              }
            }
          }
        },
        "avg_min_value": {
          "avg_bucket": {
            "buckets_path": "key_aggregates>min_value"
          }
        }
      }
    }'
    

    PS:如果您找到其他解决方案,您介意在这里分享吗?谢谢!

    【讨论】:

    • 这似乎是一个完美的解决方案。要是我们发现了这个就好了!我们没有找到直接解决这个问题的方法,所以我们采用了脚本聚合的方式:构建一个以字段“key”为键的映射,并在所有文档中为字段“key”的给定值取最小值;然后聚合这张地图的值。我不知道两者在性能方面的比较,但您的解决方案很可能应该更快!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    相关资源
    最近更新 更多