Как сделать запрос, если время находится между двумя значениями поля - PullRequest
1 голос
/ 12 марта 2020

Как мне искать документы , которые находятся между временем начала и окончания? Например, я хочу запросить следующий документ, используя время только как «18:33» или «21:32». «18:33» вернет следующий документ, а «21:32» - нет. Меня не волнует ни часть даты, ни секунды.

{
  "my start time field": "2020-01-23T18:32:21.768Z",
  "my end time field": "2020-01-23T20:32:21.768Z"
}

Я просмотрел: Использование запроса range с полями date. , но я не уверен, как смотреть только раз. Кроме того, я хочу посмотреть, находится ли время между двумя полями, а не если поле находится между двумя разами.


По сути, Elasticsearch эквивалент BETWEEN для SQL Сервер. Как этот ответ за исключением того, что я не хочу использовать текущее время, но переменную.

DECLARE @blah datetime2 = GETDATE()

SELECT  *
FROM Table1 T
WHERE CAST(@blah AS TIME) 
      BETWEEN cast(T.StartDate as TIME) AND cast(T.EndDate as TIME)

Ответы [ 3 ]

1 голос
/ 12 марта 2020

Решение 1. Существующий формат даты

Не меняя и не тратя время и часы по отдельности, я пришел к следующему решению и не думаю, что вы будете довольны тем, как ES предоставляет вам решение, но оно, безусловно, работает.

Я создал образец сопоставления, документ, запрос и ответ на основе предоставленных вами данных.

Отображение:

PUT my_date_index
{
  "mappings": {
    "properties": {
      "start_time":{
        "type": "date",
        "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
      },
      "end_time":{
        "type": "date",
        "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
      }
    }
  }
}

Образцы документов:

POST my_date_index/_doc/1
{
  "start_time": "2020-01-23T18:32:21.768Z",
  "end_time": "2020-01-23T20:32:21.768Z"
}

POST my_date_index/_doc/2
{
  "start_time": "2020-01-23T19:32:21.768Z",
  "end_time": "2020-01-23T20:32:21.768Z"
}

POST my_date_index/_doc/3
{
  "start_time": "2020-01-23T21:32:21.768Z",
  "end_time": "2020-01-23T22:32:21.768Z"
}

Запрос запроса:

POST my_date_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "script": {
            "script": {
              "source": """
                ZonedDateTime zstart_time = doc['start_time'].value;
                int zstart_hour = zstart_time.getHour();
                int zstart_minute = zstart_time.getMinute();
                int zstart_total_minutes = zstart_hour * 60 + zstart_minute;

                ZonedDateTime zend_time = doc['end_time'].value;
                int zend_hour = zend_time.getHour();
                int zend_minute = zend_time.getMinute();
                int zend_total_minutes = zend_hour * 60 + zend_minute;

                int my_input_total_minutes = params.my_input_hour * 60 + params.my_input_minute;

                if(zstart_total_minutes <= my_input_total_minutes && zend_total_minutes >= my_input_total_minutes){
                  return true;
                }

                return false;

              """,
              "params": {
                "my_input_hour": 20,
                "my_input_minute": 10
              }
            }
          }
        }
      ]
    }
  }
}

В основном

  • рассчитать количество минут от start_date

  • рассчитать количество минут от end_date

  • рассчитать количество минут из params.my_input_hour & params.my_input_minute

  • выполнить лог c в условии if как start_date <= input <= end_date, используя протоколы всех трех значений и вернуть документы соответственно.

Ответ:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 2.0,
    "hits" : [
      {
        "_index" : "my_time_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 2.0,
        "_source" : {
          "start_time" : "18:32",
          "end_time" : "20:32"
        }
      }
    ]
  }
}

Тщательно проверяйте их на предмет проблем с производительностью, когда дело доходит до решения 1 как запросы сценариев Обычно хиты выступлений, однако они пригодятся, если у вас нет выбора.

Дайте мне знать, если это поможет!

1 голос
/ 27 марта 2020

В соответствии с предложением от OP и предоставленной им ссылкой, которая соответствует l aws stackoverflow, я даю второе решение здесь:

Решение 2: Вставьте отдельные поля для часовых минут как чч: мм

Обратите внимание на используемый формат, который говорит hour_minute. Вы можете найти список форматов, доступных по вышеупомянутой ссылке.

По сути, вы заново принимаете документы с отдельным полем, которое будет иметь hour and minute values, и выполняете range queries, чтобы получить то, что вы хотите.

Отображение:

PUT my_time_index
{
  "mappings": {
    "properties": {
      "start_time":{
        "type": "date",
        "format": "hour_minute"
      },
      "end_time":{
        "type": "date",
        "format": "hour_minute"
      }
    }
  }
}

Образец документа:

POST my_time_index/_doc/1
{
  "start_time": "18:32",
  "end_time": "20:32"
}

Запрос запроса:

POST my_time_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "start_time": {
              "gte": "18:00"
            }
          }
        },
        {
          "range": {
            "end_time": {
              "lte": "21:00"
            }
          }
        }
      ]
    }
  }
}

Дайте мне знать, если это поможет!

1 голос
/ 12 марта 2020

Не хранить время в типе данных datetime на основе этого обсуждения .

Если вы хотите отфильтровать по определенному c часу дня, вы бы нужно извлечь это в собственное поле.

С помощью Kibana Dev Tools -> Консоль

Создать некоторые фиктивные данные:

POST between-research/_doc/1
{
  "my start hour": 0,
  "my end hour": 12
}

POST between-research/_doc/2
{
  "my start hour": 13,
  "my end hour": 23
}

Выполнить поиск «между»

POST between-research/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "my start hour": {
              "lte": 10
            }
          }
        },
        {
          "range": {
            "my end hour": {
              "gte": 10
            }
          }
        }
      ]
    }
  }
}
...