【问题标题】:How to query if a time is between two field values如何查询时间是否在两个字段值之间
【发布时间】:2020-03-12 16:19:16
【问题描述】:

我如何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.,但我不确定如何仅查看时间。另外,我想查看一个时间是否在两个字段之间,而不是一个字段是否在两个时间之间。


本质上,Elasticsearch 相当于 SQL Server 的 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)

【问题讨论】:

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


    【解决方案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"
                }
              }
            }
          ]
        }
      }
    }
    

    如果这有帮助,请告诉我!

    【讨论】:

      【解决方案2】:

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

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

      通过Kibana Dev Tools -> Console

      创建一些模拟数据:

      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
                  }
                }
              }
            ]
          }
        }
      }
      

      【讨论】:

        【解决方案3】:

        解决方案 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 计算分钟数

        • 使用所有三个值的分钟数执行 if 条件中的逻辑为start_date &lt;= input &lt;= 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 个单独的解决方案吗? ? 然后社区可以投票赞成另一个。然后下一个人可以有更轻松的时间。 ?解决方案2!
        • 嗨@OpsterESNinja-Kamal - meta.stackoverflow.com/a/269546/185123
        • 您好 Opster - 我愿意接受解决方案 2 作为答案,您对将它们分开感觉如何?
        • @spottedmahn 非常感谢您提供该链接并遵循 stackoverflow 的约定。很高兴帮助你,因为它帮助我学习了一些新东西。我从来不知道我可以添加多个答案。再次感谢您!
        猜你喜欢
        • 2016-07-10
        • 1970-01-01
        • 1970-01-01
        • 2014-05-25
        • 2022-01-20
        • 2022-06-12
        • 2017-11-22
        • 1970-01-01
        • 2019-10-06
        相关资源
        最近更新 更多