如何查询时间是否在两个字段值之间

时间:2020-03-12 16:19:16

标签: elasticsearch elasticsearch-dsl elasticsearch-query range-query

我如何search for documents在开始时间和结束时间之间?例如,我只想使用“ 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"
}

我已经查看过:Using the range query with date fields.,但是我不确定如何只看时间。另外,我想看看时间是否在两个字段之间,而不是时间是否在两个字段之间。


实质上,对于SQL Server,Elasticsearch等于BETWEENLike this answer,除了我不想使用当前时间,而是一个变量。

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 个答案:

答案 0 :(得分:1)

不要将时间存储在基于this discussion的日期时间数据类型中。

如果要过滤一天中的特定时间,则需要将其提取到其自己的字段中。

通过Kibana Dev Tools -> Console

创建一些模拟数据:

([^\[]+)\s\[([\w\.]+)\]\s([\w]+)\:(.+)

执行“之间”搜索

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
}

答案 1 :(得分:1)

解决方案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_hourparams.my_input_minute

  • 计算分钟数
  • 使用所有三个值的分钟数将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方面,请对它们进行彻底的性能问题测试,因为script queries通常会影响性能,但是如果没有选择,它们会派上用场。

让我知道这是否有帮助!

答案 2 :(得分:1)

根据OP的建议以及他提供的遵循stackoverflow规律的链接,我在这里提供第二种解决方案:

解决方案2:将小时为hh:mm的单独字段插入小时

请注意使用的格式为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"
            }
          }
        }
      ]
    }
  }
}

让我知道这是否有帮助!

相关问题