简体   繁体   English

Elasticsearch 查询日期范围不起作用

[英]Elasticsearch query date range does not work

I am trying to query ElasticSearch to get a result between two timestamps.我正在尝试查询 ElasticSearch 以获得两个时间戳之间的结果。 A typical record looks like一个典型的记录看起来像

{
   "_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"
   }
}

And the query I use to retrieve every shop from app_group between 2 timestamps:我用来从app_group检索 2 个时间戳之间的每个shop的查询:

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

Only returns every shop , but does not check for any timestamp .只返回每shop ,但不检查任何timestamp What's weird, is that even if I include error on purpose on the query:奇怪的是,即使我故意在查询中包含错误:

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

I got the exact same answer.我得到了完全相同的答案。 Like it does not take the query into consideration.就像它不考虑query一样。

Some notes: In Python, my code looks like:一些注意事项:在 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"
              }
           }
         }
    })

The timestamp field of the record is indeed interpreted as a date and not a String .记录的timestamp字段确实被解释为date而不是String

What do I miss?我想念什么?

(Note that this answer is for Elasticsearch 6.3 ) (请注意,此答案适用于 Elasticsearch 6.3

What worked for me was adding a mapping when creating the index.对我有用的是在创建索引时添加映射。

In the mapping you specify what kind of data your field will hold and in the case of a date you can also set a format .在映射中,您可以指定您的字段将保存哪种数据,如果是日期, 您还可以设置格式

{
    "mappings":{
        "_doc":{
            "timestamp": {
                "format": "yyyy-MM-dd'T'HH:mm:ss'Z'",
                "type": "date"
            },
        }
    }
}

In this example the format is for a specific use case I had, but you can set it up however you need .在此示例中,格式适用于我拥有的特定用例, 但您可以根据需要进行设置

This should allow you to make a date range query, like in the following example:这应该允许您进行日期范围查询,如下例所示:

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "app_group": "shop"
          }
        }
      ],
      "filter": [
        {
          "range" : {
            "timestamp" : {
                "gte": "2018-08-15T00:00:00Z", 
                "lte": "2018-08-15T23:00:00Z"
                }
            }
        }
      ]
    }
  }
}

Note that the format I'm using is slightly different than yours.请注意,我使用的格式与您的略有不同。

Some more details:更多细节:

In my particular case I had an issue with the results, since I needed an exact match of the search term, to avoid related but irrelevant results.在我的特殊情况下,我遇到了结果问题,因为我需要与搜索词完全匹配,以避免相关但不相关的结果。

In your case it seems like you might also run into this issue since you are searching for a specific "app_group".在您的情况下,您似乎也可能遇到此问题,因为您正在搜索特定的“app_group”。

To enable the exact search you can use the following mapping:要启用精确搜索,您可以使用以下映射:

{
  "settings":{
    "index":{
      "analysis":{
        "analyzer":{
          "analyzer_case_insensitive":{
            "tokenizer":"keyword",
            "filter":"lowercase"
          }
        }
      }
    }
  },
  "mappings":{
    "_doc":{
      "properties":{
        "app_group":{
          "type":"string",
          "analyzer":"analyzer_case_insensitive"
        }
      }
    }
  }
}

(Which I found in this very useful blog post , after running into several outdated methods in StackOverflow and elsewhere) (这是我在这篇非常有用的博客文章中发现的,在 StackOverflow 和其他地方遇到了几个过时的方法之后)

Basically what the provided settings are doing is tell the indexer to use the keyword tokenizer and apply the lowercase filter so that your search is case-insensitive (ie will turn everything into lowercase first, so you can search for "app_group = shop" or "app_group = Shop", etc.基本上提供的设置所做的是告诉索引器使用关键字标记器并应用小写过滤器,以便您的搜索不区分大小写(即首先将所有内容都变成小写,因此您可以搜索“app_group = shop”或“ app_group = Shop”等。

The final mapping should look similar to this (except with your own date format):最终映射应与此类似(除了您自己的日期格式):

{
  "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"
        }
      }
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM