【问题标题】:How to get a bucket for each day between start date and end date fields of a document in elasticsearch如何在elasticsearch中获取文档的开始日期和结束日期字段之间的每一天的存储桶
【发布时间】:2021-07-22 14:03:51
【问题描述】:

我在 elasticsearch 的索引中有如下文档

[
    {
        "Id": 1,
        "start": "2021-04-20T00:00:00.000000Z",
        "end": "2021-04-22T22:45:20.000000Z",
        "event_type": "A"
    },
    {
        "Id": 2,
        "start": "2021-04-23T00:01:00.000000Z",
        "end": "2021-04-26T21:50:20.000000Z",
        "event_type": "B"
    },
    {
        "Id": 3,
        "start": "2021-04-27T00:03:30.000000Z",
        "end": "2021-04-29T04:15:30.000000Z",
        "event_type": "A"
    }
]

我想计算每个event_type 的总天数。例如,对于上述文件, event_type A 在第一个文档中跨越了 3 天,"Id": 1 从 20 日(开始)到 22 日(结束),在第三个文档中又过了 3 天,"Id": 3 从 27 日(开始)到 29 日(结束)。所以我想为event_type A 计数 6。 event_type B 在第二个文档中跨越 4 天,"Id": 2 从 23 日(开始)到 26 日(结束)。所以,对于event_type B,我想算为 4。

event_type count
A 6
B 4

我知道如何使用术语聚合来获取每种事件类型的文档数

GET /split_range/_search
{
  "size": 0,
  "aggs": {
    "by_event_type": {
      "terms": {
        "field": "event_type"
      }
    }
  }
}

有没有办法在开始和结束(包括开始和结束)之间的每一天将该文档进一步拆分为多个存储桶并获得该计数?

【问题讨论】:

    标签: elasticsearch date-range elasticsearch-aggregation


    【解决方案1】:

    如果 json 有点一致,我会一直使用 pandas 来完成这类任务。

    data = [
        {
            "Id": 1,
            "start": "2021-04-20T00:00:00.000000Z",
            "end": "2021-04-22T22:45:20.000000Z",
            "event_type": "A"
        },
        {
            "Id": 2,
            "start": "2021-04-23T00:01:00.000000Z",
            "end": "2021-04-26T21:50:20.000000Z",
            "event_type": "B"
        },
        {
            "Id": 3,
            "start": "2021-04-27T00:03:30.000000Z",
            "end": "2021-04-29T04:15:30.000000Z",
            "event_type": "A"
        }
    ]
    df = pd.DataFrame(data)
    df['end'] =  pd.to_datetime(df['end']).dt.date
    df['start'] =  pd.to_datetime(df['start']).dt.date
    df["diff"] = (df["end"] - df["start"])
    print(df.head())
    

    将导致:

       Id         end event_type       start   diff
    0   1  2021-04-22          A  2021-04-20 2 days
    1   2  2021-04-26          B  2021-04-23 3 days
    2   3  2021-04-29          A  2021-04-27 2 days
    

    【讨论】:

    • 我注意到它现在向下取整,因此您需要增加一天。但你明白了
    【解决方案2】:

    您可以将 sum sub 聚合与下面提到的脚本一起使用。

    1. 在字段event_type 上使用term 聚合来获取唯一的事件类型。
    2. 添加sum 子聚合以计算每种事件类型的天数总和。
    3. sum 聚合中提供script 来计算日差。
    GET split_range/_search
    {
      "size": 0,
      "aggs": {
        "GroupByEventType": {
          "terms": {
            "field": "event_type",
            "size": 10000,
            "order": {
              "_key": "asc"
            }
          },
          "aggs": {
            "sumOfDays": {
              "sum": {
                "script": """
                    ZonedDateTime start = doc['start'].value;
                    ZonedDateTime end = doc['end'].value;
                    return start.until(end, ChronoUnit.DAYS);
                 """
              }
            }
          }
        }
      }
    }
    

    当我针对您问题中提供的示例数据集尝试上述查询时,得到了以下答案。

    {
      "aggregations" : {
        "GroupByEventType" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "A",
              "doc_count" : 2,
              "sumOfDays" : {
                "value" : 4.0
              }
            },
            {
              "key" : "B",
              "doc_count" : 1,
              "sumOfDays" : {
                "value" : 3.0
              }
            }
          ]
        }
      }
    }
    

    响应包含每个事件类型的子聚合,即天数。

    【讨论】:

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