Elasticsearch 查询日期范围不起作用

Mor*_*nor 5 python elasticsearch

我正在尝试查询 ElasticSearch 以获得两个时间戳之间的结果。一个典型的记录看起来像

{
   "_index": "cost-2018.08.09",
   "_type": "log",
   "_id": "asdasdasxsa-sdsds",
   "_score": 4.281278,
   "_source": {
      "index": "cost-2018.08.09",
      "app_group": "shop",
      "timestamp": "2018-08-09T00:00:04.349692"
   }
}
Run Code Online (Sandbox Code Playgroud)

我用来shopapp_group2 个时间戳中检索每一个的查询:

GET /cost-2018.08.09/_search?q=app_group:shop 
{
  "query": {
    "range": {
      "timestamp": {
        "gte": "2018-08-09 04:00:04",
        "lt": "2018-08-09 04:30:06"
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

只返回 every shop,但不检查 any timestamp。奇怪的是,即使我故意在查询中包含错误:

GET /cost-2018.08.09/_search?q=app_group:shop
{
  "query": {
    "range": {
      "timestamp": {
        "gte": "2018-08-asdadsx09 04:00:04",
        "lt": "2018-08-09asdasd 04:30:06"
      }
    }
 }
Run Code Online (Sandbox Code Playgroud)

我得到了完全相同的答案。就像它没有考虑query到。

一些注意事项:在 Python 中,我的代码如下所示:

result = es_client.search(index='cost-2018.07.26', q='app_group:shop', filter_path=['hits.hits._source'], body={
        "query": {
            "range": {
              "timestamp": {
                 "gte": "2018-08-09 04:00:04",
                 "lt": "2018-08-09 04:30:06"
              }
           }
         }
    })
Run Code Online (Sandbox Code Playgroud)

timestamp记录的字段确实被解释为 adate而不是 a String

我想念什么?

Aca*_*lco 5

(请注意,此答案适用于 Elasticsearch 6.3

对我有用的是在创建索引时添加映射。

在映射中,您可以指定字段将保存的数据类型,如果是日期,您还可以设置格式

{
    "mappings":{
        "_doc":{
            "timestamp": {
                "format": "yyyy-MM-dd'T'HH:mm:ss'Z'",
                "type": "date"
            },
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,格式适用于我拥有的特定用例,但您可以根据需要进行设置

这应该允许您进行日期范围查询,如下例所示:

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "app_group": "shop"
          }
        }
      ],
      "filter": [
        {
          "range" : {
            "timestamp" : {
                "gte": "2018-08-15T00:00:00Z", 
                "lte": "2018-08-15T23:00:00Z"
                }
            }
        }
      ]
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我使用的格式与您的略有不同。

更多细节:

在我的特殊情况下,我遇到了结果问题,因为我需要与搜索词完全匹配,以避免相关但不相关的结果。

在您的情况下,您似乎也可能遇到此问题,因为您正在搜索特定的“app_group”。

要启用精确搜索,您可以使用以下映射:

{
  "settings":{
    "index":{
      "analysis":{
        "analyzer":{
          "analyzer_case_insensitive":{
            "tokenizer":"keyword",
            "filter":"lowercase"
          }
        }
      }
    }
  },
  "mappings":{
    "_doc":{
      "properties":{
        "app_group":{
          "type":"string",
          "analyzer":"analyzer_case_insensitive"
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

(这是我在这篇非常有用的博客文章中发现的,在 StackOverflow 和其他地方遇到了几个过时的方法之后)

基本上提供的设置所做的是告诉索引器使用关键字标记器并应用小写过滤器,以便您的搜索不区分大小写(即首先将所有内容都变成小写,因此您可以搜索“app_group = shop”或“ app_group = Shop”等。

最终映射应与此类似(除了您自己的日期格式):

{
  "settings":{
    "index":{
      "analysis":{
        "analyzer":{
          "analyzer_case_insensitive":{
            "tokenizer":"keyword",
            "filter":"lowercase"
          }
        }
      }
    }
  },

  "mappings": {
    "_doc": {
      "properties": {
        "timestamp": {
          "type":   "date",
          "format": "yyyy-MM-dd'T'HH:mm:ss'Z'"
        },
        "app_group": {
          "type":"text",
          "analyzer":"analyzer_case_insensitive"
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)