【问题标题】:ElasticSearch: How to query a date field using an hours-range filterElasticSearch:如何使用小时范围过滤器查询日期字段
【发布时间】:2015-11-05 01:20:07
【问题描述】:

目前,我已经知道如何从(时间戳)日期字段中过滤日期范围。这很简单:

"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 之间发生的所有事件?

【问题讨论】:

  • 在这些时间之间,任何一天?
  • 假设我想获取 2015 年 10 月 1 日到 2015 年 12 月 31 日之间的所有记录,但只有在这个时间范围内发生的记录:“8:00:00”和“10 :00:00"
  • 类似的问题,但不一样。在另一个中,我假设有另一个名为“时间”的字段改变了问题。

标签: elasticsearch


【解决方案1】:

您可以使用 range 过滤器过滤正确的日期,然后使用 script 过滤器过滤所需的时间,如下所示:

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

请注意,您需要确保enable dynamic scripting 才能使此查询起作用。

【讨论】:

  • 谢谢。它工作完美。顺便说一句,我尝试使用“getMinuteOfHour”方法添加另一个脚本来过滤分钟,但它没有用。有什么建议吗?
  • 嗨@Val你能告诉我getHourOfDay()方法来自哪里吗? groovy 脚本引擎是否使用joda 进行日期时间操作?我找不到任何文档
  • @ChintanShah25 是的,doc['field'].datedatelong 类型的所有字段返回一个 Joda MutableDateTime 对象。同意,官方文档中没有明确提及,但您可以在 2010 年的 original ticket 中找到该信息。
【解决方案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"
            }
          }
        }
      ]
    }
  }
}

这有帮助吗?

【讨论】:

  • 现在,我的字段“date”有这种类型:{“type”:“date”,“format”:“dateOptionalTime”},它支持这样的记录 2015-11-04T22:10 :02 不幸的是我无法修改我的索引
  • 即使在我的应用程序中,我也有相同的格式,但问题是你只能像 "gte" : "2015-10-02T13:34:09", "lte" : "2015-10-05T12: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),请参阅 reference doc详情。

【讨论】:

  • 你能告诉我我的语法是否适合我的场景吗?想要获取从前一天晚上 7 点到今天晚上 7 点的日期 range.setGte("now-1d/d+19h"); range.setLte("now-24h/d+19h")
  • 我认为前一天晚上 7 点应该是 range.setGte("now-2d/d+19h");..?但无法检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多