在我的 ElasticHQ映射中:

@timestamp  date    yyyy-MM-dd HH:mm:ssZZZ
...
date    date    yyyy-MM-dd HH:mm:ssZZZ

在上面,我有两种类型的日期字段,每种类型都具有到相同格式的映射。

数据中:
"@timestamp": "2014-05-21 23:22:47UTC"
....
"date": "2014-05-22 05:08:09-0400",

如上所述,日期格式未映射到ES认为我的日期格式为的格式。我认为在索引时间发生了一些棘手的事情(我不在身边)。

也很有趣:当使用如下所示的过滤范围查询时,我得到一个解析异常,解释说我的日期太短了:
GET _search
{
   "query": {
       "filtered": {
          "query": {
            "match_all": {}
          },
          "filter": {
              "range": {
                 "date": {
                    "from": "2013-11-23 07:00:29",
                    "to": "2015-11-23 07:00:29",
                    "time_zone": "+04:00"
                 }
              }
          }
       }
   }
}

但是,由于文档中的日期格式,我假设使用以下内容进行搜索可通过ES的错误检查,但未返回任何结果。
    GET _search
{
   "query": {
       "filtered": {
          "query": {
            "match_all": {}
          },
          "filter": {
              "range": {
                 "date": {
                    "from": "2013-11-23 07:00:29UTC",
                    "to": "2015-11-23 07:00:29UTC",
                    "time_zone": "+04:00"
                 }
              }
          }
       }
   }
}

我的问题是:鉴于以上所述,有什么方法可以避免不得不重新索引和更改映射并继续搜索格式错误的数据?在此特定群集中,我们大约有1TB的数据,出于明显的原因,我们希望将其保持原样。

还尝试执行符合数据中内容的查询:
"query": {
   "range": {
      "date": {
         "gte": "2014-05-22 05:08:09-0400",
         "to": "2015-05-22 05:08:09-0400"
      }
   }
}

最佳答案

您文档中的日期实际上确实与映射中的日期格式一致,即yyyy-MM-dd HH:mm:ssZZZ
在日期格式模式中,ZZZ代表RFC 822时区(例如-04:00,+ 04:00,EST,UTC,GMT等),因此数据中的日期确实符合要求,否则它们将不符合要求首先被索引。

但是,最佳实践是始终在将索引编入索引之前,始终确保将日期转换为UTC(或整个文档库所共有的其他时区,在您的上下文中有意义)。

至于触发错误的查询,由于末尾缺少时区,因此2013-11-23 07:00:29不符合日期格式。如您所知,在最后添加UTC可解决查询解析问题(即缺少的ZZZ部分),但您仍然可能无法获得任何结果。

现在回答您的问题,您有两个主要任务要做:

  • 修复索引编制过程/组件,以确保所有日期都在公共(public)时区(通常为UTC)中
  • 修复现有数据以将索引文档中的日期转换为相同的时区

  • 1TB是要重新索引以修复一个或两个字段的大量数据。我不知道您的文档是什么样子,但这并不重要。解决这个问题的方法是对所有文档进行部分更新,为此,我看到了两种不同的解决方案,两种解决方案的目的都是修复@timestampdate字段:
  • 根据您的ES版本,您可以使用update-by-query plugin,但通过脚本转换日期会比较麻烦。
  • 或者,您可以编写一个即席客户端,对所有现有文档进行scroll,然后对每个文档进行partial update并将其发送回in bulk

  • 给定您拥有的数据量,解决方案2似乎更合适。

    所以...您的即席脚本应首先发出滚动查询以获取如下滚动ID:
    curl -XGET 'server:9200/your_index/_search?search_type=scan&scroll=1m' -d '{
        "query": { "match_all": {}},
        "size":  1000
    }'
    

    结果,您将获得一个滚动ID,您现在可以使用该滚动ID遍历所有数据
    curl -XGET 'server:9200/_search/scroll?_source=date,@timestamp&scroll=1m' -d 'your_scroll_id'
    

    现在您可以进行迭代的1000次匹配(您可以根据自己的里程在上面的第一个查询中取消/增加size参数)。

    对于每次获得的匹配,您只有两个需要修复的日期字段。然后,您可以使用solution like this将日期转换为您选择的标准时区。

    最后,您可以像这样批量发送1000个更新的部分文档:
    curl -XPOST server:9200/_bulk -d '
    { "update" : {"_id" : "1", "_type" : "your_type", "_index" : "your_index"} }
    { "doc" : {"date" : "2013-11-23 07:00:29Z", "@timestamp": "2013-11-23 07:00:29Z"} }
    { "update" : {"_id" : "2", "_type" : "your_type", "_index" : "your_index"} }
    { "doc" : {"date" : "2014-09-12 06:00:29Z", "@timestamp": "2014-09-12 06:00:29Z"} }
    ...
    '
    

    冲洗并重复下一次迭代...

    我希望这会给您一些入门的入门指南。如果你有问题就告诉我们。

    关于elasticsearch - ElasticSearch日期字段映射格式错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30107313/

    10-17 03:04