【问题标题】:ElasticSearch Aggregation over Top Hits热门点击的 ElasticSearch 聚合
【发布时间】:2016-11-06 19:37:30
【问题描述】:

我的数据如下:

{"action":"CREATE","docs":1,"date":"2016 Jun 26 12:00:12","userid":"1234"}
{"action":"REPLACE","docs":2,"date":"2016 Jun 27 12:00:12","userid":"1234"}
{"action":"REPLACE","docs":1,"date":"2016 Jun 27 13:00:12","userid":"1234"}
{"action":"CREATE","docs":1,"date":"2016 Jun 28 12:00:12","userid":"3431"}
{"action":"REPLACE","docs":2,"date":"2016 Jun 28 13:00:12","userid":"3431"}
{"action":"CREATE","docs":1,"date":"2016 Jun 29 12:00:12","userid":"9999"}

为了按日期(降序)获取每个唯一用户订单的记录,我使用了 Top Hits,如下所示:

"aggs": {
  "user_bucket": {
    "terms": {
      "field": "userid"
    },
    "aggs": {
      "user_latest_count": {
        "top_hits": {
          "size": 1,
          "sort": [
            {
              "data": {
                "order": "desc"
              }
            }
          ],
          "_source": {
            "include": [
              "docs"
            ]
          }
        }
      }
    }
  }
}

以上查询结果如下:

{"action":"REPLACE","docs":1,"date":"2016 Jun 27 13:00:12","userid":"1234"}
{"action":"REPLACE","docs":2,"date":"2016 Jun 28 13:00:12","userid":"3431"}
{"action":"CREATE","docs":1,"date":"2016 Jun 29 12:00:12","userid":"9999"}

现在,我想进一步汇总,结果如下:

{"sum_of_different_buckets": 4}

但不确定如何从上面获得的结果中SUM字段“docs”值。

【问题讨论】:

  • 我不明白你想要达到什么目的。总结哪些文档值?结果应该如何?
  • 我已编辑问题,请立即查看。基本上,我需要在 Top Hits 聚合之上再增加一层聚合,以便获得字段“docs”的总和。
  • 我不认为这是可能的,因为您想使用 top_hits 的输出,并且此聚合之后不能用于其他聚合。你不能只在你自己的代码/应用程序中求和吗?
  • 您可以在查询中添加排序,然后使用terms 聚合,然后在该聚合上使用docs 字段的sum 聚合。

标签: elasticsearch


【解决方案1】:

您还可以在聚合中任意嵌套聚合,以从数据中提取您需要的汇总数据。可能在示例作品下方。

"aggs" : {
    "sum_of_different_buckets" : { "sum" : { "field" : "docs" } }
}

【讨论】:

    【解决方案2】:

    您可以在 top_hit 的并行级别上进行其他聚合,但您不能在下面有任何 sub_aggregation top_hit . elasticsearch 不支持它。 here is the link to github issue

    但是如果你想在同一级别上求和,你可以使用下面的方法。

    "aggs": {
        "top_hits_agg": {
            "top_hits": {
                "size": 10,
                "_source": {
                  "includes": ["docs"]
                }
            }
        },
        "sum_agg": {
            "sum": {
                "field": "docs"
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用scripted_metricsum_bucket 管道聚合。 scripted_metric 聚合允许您编写自己的 map-reduce 逻辑,因此您可以为每个术语返回单个指标。

      POST rahul_test/_search
      {
        "size": 0,
        "aggs": {
          "user_bucket": {
            "terms": {
              "field": "userid",
              "size": 10000,
              "min_doc_count": 1
            },
            "aggs": {
              "user_latest_count": {
                "scripted_metric": {
                  "init_script": "state.timestamp_latest = 0L; state.last_value = 0",
                  "map_script": "def date_as_millis = doc['date'].getValue().toInstant().toEpochMilli(); if (date_as_millis > state.timestamp_latest) { state.timestamp_latest = date_as_millis; state.last_value = doc.docs.value;}",
                  "combine_script": "return state",
                  "reduce_script": "def last_value = 0; def timestamp_latest = 0L; for (s in states) {if (s.timestamp_latest > (timestamp_latest)) {timestamp_latest = s.timestamp_latest; last_value = s.last_value;}} return last_value;"
                }
              }
            }
          },
          "sum_user_latest_counts": {
            "sum_bucket": {
              "buckets_path": "user_bucket>user_latest_count.value"
            }
          }
        }
      }
      
      • init_script 在状态对象中创建 2 个字段 timestamp_latestlast_value(每个分片一个状态对象)。
      • map_script 对父 terms 聚合返回的桶中收集的每个文档执行一次。如果根据文档的date定义date_as_millis,然后比较date_as_millisstate.timestamp_latest,最后从分片更新state.last_value
      • combine_script 从每个分片返回状态。
      • reduce_script 遍历每个分片返回的 s.timestamp_latest 的值,并从具有最新时间戳 (last_value) 的文档中返回单个值。

      此时,每个userid 都有最新的docs 值。然后我们使用sum_bucket 管道聚合来汇总所有最新的docs 值,返回4 的值。

      {
        "took" : 2,
        "timed_out" : false,
        "_shards" : {
          "total" : 1,
          "successful" : 1,
          "skipped" : 0,
          "failed" : 0
        },
        "hits" : {
          "total" : 6,
          "max_score" : 0.0,
          "hits" : [ ]
        },
        "aggregations" : {
          "user_bucket" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "1234",
                "doc_count" : 3,
                "user_latest_count" : {
                  "value" : 1
                }
              },
              {
                "key" : "3431",
                "doc_count" : 2,
                "user_latest_count" : {
                  "value" : 2
                }
              },
              {
                "key" : "9999",
                "doc_count" : 1,
                "user_latest_count" : {
                  "value" : 1
                }
              }
            ]
          },
          "sum_user_latest_counts" : {
            "value" : 4.0
          }
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多