按星期几和时间过滤 Elasticsearch

SGo*_*lds 5 elasticsearch elasticsearch-dsl

我在 Elasticsearch 中有一个企业索引。索引中的每个文档代表一个企业,每个企业都有business_hours。我试图允许使用星期几和时间来过滤营业时间。例如,我们希望能够做一个过滤器来显示周二晚上 6:00PM 之后开放的所有业务, 我认为我们应该有一个具有以下映射的字段:

  {
      "mappings": {
        "properties": {
          
          "business_hours": {
                             "type": "date_range",
                            "format": "w'T'hh:mma"
          }
        }
      }
    }
Run Code Online (Sandbox Code Playgroud)

每个文档都会有一个business_hours 数组。因此,周一上午 9:00 - 下午 5:00 和周二上午 9:30 - 下午 5:00 营业的商店将如下所示:

POST my-index/_doc
    {
      "name": "My Store",
      "business_hours": [
        {
        "gte": "1T09:00AM",
        "lte": "1T05:00PM"
        },
        {
        "gte": "2T09:30AM",
        "lte": "2T05:00PM"
        }
      ]
    }
Run Code Online (Sandbox Code Playgroud)

我尝试搜索此文档并查询它,但是时间过滤器不起作用,它们看起来像是被忽略了......Elasticsearch 是否支持按一周中的某一天进行过滤,或者是否需要是实际的日期时间?

这是我使用的查询。它应该过滤周三营业的营业时间,但它返回了上面的文件,其中只有周一和周二的营业时间

GET my-index/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "business_hours": {
              "gte": "3T10:00AM",
              "lte": "3T05:00PM",
              "relation": "CONTAINS"
            }
          }
        }
      ]
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Val*_*Val 3

使用字段的想法range是个好主意。但是,date_range我建议使用字段,而不是适用于绝对日期的integer_range

由于每天包含 1440 分钟,我的建议是将开放时间编码为自午夜以来的分钟数,并在该数字前加上当天的索引(星期一 = 1、星期二 = 2 等)。将给定的小时转换为自午夜以来的分钟的公式非常简单:

(60 * HH) + MM 

Note: HH is in 24 hours format, not AM/PM, but that's a detail
Run Code Online (Sandbox Code Playgroud)

以上面的例子为例,它会产生这样的结果:

POST my-index/_doc
{
  "business_hours": [
    {
      "gte": 10540,       <--- Monday (1), 540 minutes after midnight
      "lte": 11020        <--- Monday (1), 1020 minutes after midnight
    },
    {
      "gte": 20570,       <--- Tuesday (2), 570 minutes after midnight
      "lte": 21020        <--- Tuesday (2), 1020 minutes after midnight
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

这样range查询就变得很简单,可以消除任何与日期相关的问题。例如,下面的查询通过搜索周一早上 6 点到下午 5 点营业的企业来检索上面的文档

GET my-index/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "business_hours": {
              "gte": "10600",         <--- Monday (1), 600 minutes after midnight
              "lte": "11020",         <--- Monday (1), 1020 minutes after midnight
              "relation": "CONTAINS"
            }
          }
        }
      ]
    }
  }
}
Run Code Online (Sandbox Code Playgroud)