代码之家  ›  专栏  ›  技术社区  ›  Mornor

Elasticsearch查询日期范围不工作

  •  1
  • Mornor  · 技术社区  · 6 年前

    我正在尝试查询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"
       }
    }
    

    我用来检索 shop app_group 两个时间戳之间:

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

    每次只返回 商店 ,但不检查任何 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"
          }
        }
     }
    

    我得到了完全相同的答案。好像不需要 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"
                  }
               }
             }
        })
    

    这个 时间戳 记录字段确实被解释为 date 而不是 String .

    我错过了什么?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Acapulco Tatiana Perere    6 年前

    (注意这个答案是 弹性搜索6.3 )

    对我有用的是 adding a mapping when creating the index.

    在映射中,指定字段将保存的数据类型,如果是日期 you can also set a format .

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

    在本例中,格式是针对我拥有的一个特定用例, but you can set it up however you need .

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

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

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

    更多细节:

    在我的特殊情况下,我对搜索结果有意见,因为我需要搜索词的精确匹配,以避免相关但不相关的结果。

    在您的情况下,似乎您也会遇到这个问题,因为您正在搜索一个特定的“应用程序组”。

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

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

    (我在这里找到的 very useful blog post ,在StackOverflow和其他地方遇到几个过时的方法之后)

    基本上,所提供的设置是告诉索引器 use the keyword tokenizer 然后申请 the lowercase filter 所以你的搜索是不区分大小写的(也就是说,会先把所有内容都变成小写,这样你就可以搜索“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"
            }
          }
        }
      }
    }