簡體   English   中英

彈性查詢每天按指定時間范圍聚合

[英]Elastic query aggregate by specified time range a day

嗨,我需要編寫一個特定的查詢,該查詢將在幾天內按選定時間范圍內的工作班次匯總數據。 問題是我不想直接在 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)"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

但結果我得到 null 的值,因為時間范圍沒有用日期指定。

  "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": []
  }


當我為整個查詢生成所需時間戳范圍的所有 date_ranges 時,結果還可以,這是獲得所需結果的唯一方法,還是有人可以建議如何更新查詢以滿足我的要求? 謝謝

您在data_range聚合中看不到任何存儲桶的原因與datetime時間與date推斷有關——類似於我前一段時間在這里討論的那個。

簡而言之,在處理時間值( HH:mm )而不是完整的日期時間值( MM-dd-yyyy HH:mm )時, date_range聚合看起來令人困惑,因為:

  • 如果沒有提供year ,則默認為1970
  • 如果沒有提供month ,則默認為一月
  • 如果沒有提供day ,則默認為該月的 1 日(如果沒有提供月份,則默認為Jan
  • 等等。

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

"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. 將此新字段添加到每個文檔(或使用攝取管道,或腳本化的_update_by_query調用):
{
  "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": [

這就是它的全部!

PS 在幕后, time值將自動分配給 1970但這很好,因為您只對時間值感興趣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM