【问题标题】:Elastic query aggregate by specified time range a day弹性查询每天按指定时间范围聚合
【发布时间】:2021-05-20 06:19:04
【问题描述】:

您好,我需要编写一个特定的查询,该查询将在几天内按选定时间范围内的工作班次汇总数据。问题是我不想直接在 date_range 聚合中指定所有范围,只想为聚合的特定日期指定从 -> 到时间范围。 有没有可能如何以简单的方式做到这一点?

我有这样的疑问:

{
    "_source": false,
    "size": 10000,
    "query": {
        "bool": {
            "must": [
                {
                    "terms": {
                        "streamId": [
                            "ENRG_0054"
                        ]
                    }
                },
                {
                    "range": {
                        "timestamp": {
                            "gte": "2021-02-01T00:00:00Z",
                            "lte": "2021-02-10T01:00:00Z"
                        }
                    }
                }
            ]
        }
    },
    "sort": [
        {
            "timestamp": {
                "order": "asc"
            }
        },
        {
            "_score": {
                "order": "asc"
            }
        }
    ],
    "aggs": {
        "streamId": {
            "terms": {
                "field": "streamId",
                "size": 10000
            },
            "aggs": {
                "days": {
                    "date_histogram": {
                        "field": "timestamp",
                        "interval": "1d"
                    },
                    "aggs": {
                        "shifts": {
                            "date_range": {
                                "field": "timestamp",
                                "format": "HH:mm",
                                "ranges": [
                                    {
                                        "key": "MORNING",
                                        "from": "06:00",
                                        "to": "14:00"
                                    },
                                    {
                                        "key": "AFTERNOON",
                                        "from": "14:00",
                                        "to": "22:00"
                                    }
                                ],
                                "keyed": true
                            },
                            "aggs": {
                                "MAX": {
                                    "max": {
                                        "field": "@floatMessage.value.value"
                                    }
                                },
                                "MIN": {
                                    "min": {
                                        "field": "@floatMessage.value.value"
                                    }
                                },
                                "DIFF": {
                                    "bucket_script": {
                                        "buckets_path": {
                                            "min": "MIN",
                                            "max": "MAX"
                                        },
                                        "script": {
                                            "source": "return (params.max-params.min)"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

但是在结果中我得到的值是空的,因为时间范围没有用日期指定。

  "aggregations": {
        "streamId": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": "ENRG_0054",
                    "doc_count": 13343,
                    "days": {
                        "buckets": [
                            {
                                "key_as_string": "2021-02-01T00:00:00.000Z",
                                "key": 1612137600000,
                                "doc_count": 2763,
                                "shifts": {
                                    "buckets": {
                                        "MORNING": {
                                            "from": 2.16E7,
                                            "from_as_string": "06:00",
                                            "to": 5.04E7,
                                            "to_as_string": "14:00",
                                            "doc_count": 0,
                                            "MIN": {
                                                "value": null
                                            },
                                            "MAX": {
                                                "value": null
                                            }
                                        },
                                        "AFTERNOON": {
                                            "from": 5.04E7,
                                            "from_as_string": "14:00",
                                            "to": 7.92E7,
                                            "to_as_string": "22:00",
                                            "doc_count": 0,
                                            "MIN": {
                                                "value": null
                                            },
                                            "MAX": {
                                                "value": null
                                            }
                                        }
                                    }
                                }
                            },

示例文档:

{
    "streamId": "ENRG_0054",
    "created": "2021-02-01T00:19:42.905Z",
    "extra": {},
    "location": null,
    "model": "floatMessage",
    "id": "6017491eb112b21488f6c843",
    "value": {
      "unit": "°C",
      "value": 18.94,
      "messageProcessed": "2021-02-01T00:19:41.595Z"
    },
    "timestamp": "2021-02-01T00:19:39.161Z",
    "tags": []
  }


当我为整个查询生成所需时间戳范围的所有日期范围时,结果还可以,这是获得所需结果的唯一方法,还是有人可以建议如何更新查询以满足我的要求? 谢谢

【问题讨论】:

  • 你能分享一些示例文档吗?我不知道@floatMessage 长什么样。
  • 确定我已经编辑了主帖

标签: elasticsearch elasticsearch-5 elasticsearch-aggregation elasticsearch-query elasticsearch-date


【解决方案1】:

您在data_range 聚合中看不到任何存储桶的原因与datetimedate 的推断有关——类似于不久前的I discussed here

简而言之,date_range 聚合出现在处理时间值 (HH:mm) 时与完整日期时间值 (MM-dd-yyyy HH:mm) 相比令人困惑,因为:

  • 如果没有提供year,则默认为1970
  • 如果没有提供month,则默认为Jan
  • 如果没有提供day,则默认为每月1号(如果未提供月份,则默认为一月
  • 等等。

你看,如果你只添加了年份组件:

"date_range": {
  "field": "timestamp",
  "format": "HH:mm yyyy",    <---
  "ranges": [
    {
      "key": "MORNING",
      "from": "06:00 2021",  <---
      "to": "14:00 2021"     <---
    }
  ],
  "keyed": true
}

Elasticsearch 会返回:

"MORNING" : {
  "from" : 2.16E7,
  "from_as_string" : "06:00 1970",   <--- ?
  "to" : 5.04E7,
  "to_as_string" : "14:00 1970",     <--- ?
  ...
}

添加month 将解决这个特定的时间点问题,但当然会引入只能在一年的一个月内进行聚合的问题。

所以我提出以下建议

  1. 在您的映射中再添加一个名为 timedate 字段:
{
  "mappings": {
    "properties": {
      "streamId": {
        "type": "keyword"
      },
      ...
      "time": {
        "type": "date",             <---
        "format": "HH:mm:ss.SSSz"
      }
    }
  }
}
  1. 将此新字段添加到每个文档(或使用ingest pipelinescripted _update_by_query call):
{
  "streamId": "ENRG_0054",
  ...
  "timestamp": "2021-02-01T00:19:39.161Z",
  "time": "00:19:39.161Z",                 <---
  "tags": []
}
  1. 使用与上述相同的查询,但改为在 time 字段上进行聚合
"days": {
  "date_histogram": {
    "field": "timestamp",     <---
    "interval": "1d"
  },
  "aggs": {
    "shifts": {
      "date_range": {
        "field": "time",      <---
        "format": "HH:mm",
        "ranges": [

就是这样!

附:在后台,time 值将是 auto-assigned to 1970 但这很好,因为您只对 time 值感兴趣。

【讨论】:

  • 这个@Martin 运气好吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
  • 2015-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多