ElasticSearch: как запросить поле даты с помощью фильтра часового диапазона

В настоящее время я уже знаю, как фильтровать диапазон дней из поля даты (timestamp). Это легко:

"range": {
    "date": {
        "gte": "2015-11-01",
        "lte": "2015-11-30"
    }
}

Но как фильтровать даты, когда вас интересуют диапазоны, основанные на часах, таких как gte: "8:00:00" и lte: "10:00:00"? Это возможно?

Мое требование другими словами: Как получить все события, происходящие в этом месяце (15-11-01/15-11-30), но только между 8:00:00 и 10:00:00?

Ответ 1

Вы можете сделать это с помощью фильтра range для фильтрации правильных дней, а затем с фильтром script для фильтрации желаемых часов, например:

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "range": {
                "date": {
                  "gte": "2015-11-01",
                  "lte": "2015-11-30"
                }
              }
            },
            {
              "script": {
                "script": "doc.date.date.getHourOfDay() >= min && doc.date.date.getHourOfDay() <= max",
                "params": {
                  "min": 8,
                  "max": 10
                }
              }
            }
          ]
        }
      }
    }
  }
}

Обратите внимание, что вам нужно убедиться, что включить динамический скриптинг, чтобы этот запрос работал.

Ответ 2

Если я правильно понял ваш вопрос, я думаю, вам нужно добавить новое поле, которое индексирует только время, например

PUT your_index
{
  "mappings": {
    "your_type": {
      "properties": {
        "time": {
          "type":   "date",
          "format": "HH:mm:ss"
        }
      }
    }
  }
}

Затем вы можете запросить такой

{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "date": {
              "gte": "2015-11-01",
              "lte": "2015-11-30"
            }
          }
        },
        {
          "range": {
            "time": {
              "gte": "08:00:00",
              "lte": "10:00:00"
            }
          }
        }
      ]
    }
  }
}

Помогает ли это?

Ответ 3

Вот то, что я когда-то использовал только для получения результатов от начала текущего дня до 6 вечера:

{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "query": "(log_message:\"My Search String\")"
          }
        },
        {
          "range": {
            "@timestamp": {
              "time_zone": "CET",
              "gt": "now-24h/d",
              "lte": "now-24h/d+18h"
            }
          }
        }
      ]
    }
  }
}

важная часть - "now-24h/d", которая будет округляться до полуночи/начала текущего дня, хотя это немного сложно, поскольку это зависит от того, используете ли вы gt/lt (e), см. справочный документ для деталей.