【问题标题】:How to add paging in Elasticsearch's aggregation?如何在 Elasticsearch 的聚合中添加分页?
【发布时间】:2018-05-02 23:05:57
【问题描述】:

我有一个elasticsearch请求如下:

{
    "size":0,
    "aggs":{
        "group_by_state":{
            "terms":{
                "field":"poi_id"
            },
            "aggs":{
                "sum(price)":{
                    "sum":{
                        "field":"price"
                    }
                }
            }
        }
    }
}

我想在这个请求中添加分页,就像

select poi_id, sum(price) from table group by poi_id limit 0,2

我搜索了很多,找到了一个关于它的链接:https://github.com/elastic/elasticsearch/issues/4915

但是我还是没有得到实现方法。

有什么方法可以通过 Elasticsearch 本身而不是我的应用程序来实现?

【问题讨论】:

    标签: elasticsearch paging elasticsearch-aggregation


    【解决方案1】:

    我目前正在研究一种用于分页聚合结果的解决方案。您要使用的是partition。官方文档中的这一部分非常有帮助。 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html#_filtering_values_with_partitions

    为了调整您的示例,terms 设置将更新如下。

    {
        "size":0,
        "aggs":{
            "group_by_state":{
                "terms":{
                    "field":"poi_id",
                    "include": {
                        "partition": 0,
                        "num_of_partitions": 100
                    },
                    "size": 10000
                },
                "aggs":{
                    "sum(price)":{
                        "sum":{
                            "field":"price"
                        }
                    }
                }
            }
        }
    }
    

    这会将您的结果分为 100 个分区 (num_of_partitions),每个分区 (size) 的最大大小为 10k 个结果,并检索第一个这样的分区 (partition: 0)

    如果您正在聚合的字段有超过 10k 个唯一值(并希望返回所有值),您将需要增加 size 值或可能基于动态计算 sizenum_of_partitions你的领域的基数。 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html#search-aggregations-metrics-cardinality-aggregation

    您可能还想使用show_term_doc_count_error 设置来确保您的聚合返回准确的计数。 https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html#_per_bucket_document_count_error

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      聚会迟到了,但刚刚在 v6.3+ 中发现了 'composite' 聚合。这些允许:
      1. 更“类似 Sql”的分组
      2.使用'after_key'进行分页。
      拯救了我们的一天,希望它也能帮助其他人。

      例如,获取 2 个日期之间每小时的点击次数,按 5 个字段分组:

      GET myindex-idx/_search
      {
        "query": {
          "bool": {
            "must": [
              {"match": {"docType": "myDOcType"}}, 
              {"range": {
                "@date": {"gte": "2019-06-19T21:00:00", "lt": "2019-06-19T22:00:00"}
                }
              }
            ]
          }
        }, 
        "size": 0, 
        "aggs": {
          "mybuckets": {
            "composite": {
              "size": 100, 
              "sources": [
                {"@date": {
                  "date_histogram": {
                    "field": "@date", 
                    "interval": "hour", 
                    "format": "date_hour"}
                  }
                }, 
                {"field_1": {"terms": {"field": "field_1"}}}, 
                {"field_2": {"terms": {"field": "field_2"}}}, 
                {"field_3": {"terms": {"field": "field_3"}}}, 
                {"field_4": {"terms": {"field": "field_4"}}}, 
                {"field_5": {"terms": {"field": "field_5"}}}
              ]
            }
          }
        }
      }
      

      生产:

      {
        "took": 255,
        "timed_out": false,
        "_shards": {
          "total": 80,
          "successful": 80,
          "skipped": 0,
          "failed": 0
        },
        "hits": {
          "total": 46989,
          "max_score": 0,
          "hits": []
        },
        "aggregations": {
          "mybuckets": {
            "after_key": {
              "@date": "2019-06-19T21",
              "field_1": 262,
              "field_2": 347,
              "field_3": 945,
              "field_4": 2258,
              "field_5": 0
            },
            "buckets": [
              {
                "key": {
                  "@date": "2019-06-19T21",
                  "field_1": 56,
                  "field_2": 106,
                  "field_3": 13224,
                  "field_4": 46239,
                  "field_5": 0
                },
                "doc_count": 3
              },
              {
                "key": {
                  "@date": "2019-06-19T21",
                  "field_1": 56,
                  "field_2": 106,
                  "field_3": 32338,
                  "field_4": 76919,
                  "field_5": 0
                },
                "doc_count": 2
              },
              ....
      

      在这样发出的分页查询之后,使用查询 'after' 对象中的 'after_key 对象:

      GET myindex-idx/_search
      {
        "query": {
          "bool": {
            "must": [
              {"match": {"docType": "myDOcType"}}, 
              {"range": {
                "@date": {"gte": "2019-06-19T21:00:00", "lt": "2019-06-19T22:00:00"}
                }
              }
            ]
          }
        }, 
        "size": 0, 
        "aggs": {
          "mybuckets": {
            "composite": {
              "size": 100, 
              "sources": [
                {"@date": {
                  "date_histogram": {
                    "field": "@date", 
                    "interval": "hour", 
                    "format": "date_hour"}
                  }
                }, 
                {"field_1": {"terms": {"field": "field_1"}}}, 
                {"field_2": {"terms": {"field": "field_2"}}}, 
                {"field_3": {"terms": {"field": "field_3"}}}, 
                {"field_4": {"terms": {"field": "field_4"}}}, 
                {"field_5": {"terms": {"field": "field_5"}}}
              ],
            "after": {
              "@date": "2019-06-19T21",
              "field_1": 262,
              "field_2": 347,
              "field_3": 945,
              "field_4": 2258,
              "field_5": 0
              }
            }
          }
        }
      }
      

      这会遍历结果,直到 mybuckets 返回空

      【讨论】:

      • 您能否添加一个示例来帮助解决原始问题中的问题
      【解决方案3】:

      您可以在请求中使用参数 from 和 size。请参阅https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-from-size.html 了解更多信息。您的请求将是这样的:

      {
          "from" : 0, 
          "size" : 10,
          "aggs":{
              "group_by_state":{
                  "terms":{
                      "field":"poi_id"
                  },
                  "aggs":{
                      "sum(price)":{
                          "sum":{
                              "field":"price"
                          }
                      }
                  }
              }
          }
      }
      

      【讨论】:

      • 似乎 from 和 size 对聚合不起作用。我在聚合请求中添加了一个 from:0 和 size:1,elasticsearch 返回三个存储桶。
      • 好的,我看了一下,size 参数必须低于你的“field”:“price”参数。但是弹性搜索似乎不支持聚合中的分页。有几个stackoverflow线程,例如stackoverflow.com/questions/27776582/… - 似乎在实际的 es 版本中它是相同的......
      • 分页在聚合中不起作用。阅读discuss.elastic.co/t/pagination-in-aggregation/79423/…
      猜你喜欢
      • 1970-01-01
      • 2018-06-17
      • 2014-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-01
      • 2019-09-17
      • 2016-04-23
      相关资源
      最近更新 更多