【问题标题】:Elasticsearch - query dates without a specified timezoneElasticsearch - 查询没有指定时区的日期
【发布时间】:2015-11-22 05:40:11
【问题描述】:

我有一个具有以下映射的索引 - 日期的标准格式。在第二条记录中,指定的时间实际上是本地时间 - 但 ES 将其视为 UTC。

尽管 ES 在内部将所有已解析的日期时间转换为 UTC,但它显然也必须存储原始字符串。

我的问题是是否(以及如何)可以查询所有 scheduleDT 值没有明确指定时区的记录。

{
   "curator_v3": {
      "mappings": {
         "published": {
            "analyzer": "classic",
            "numeric_detection": true,
            "properties": {
               "Id": {
                  "type": "string",
                  "index": "not_analyzed",
                  "include_in_all": false
               },
               "createDT": {
                  "type": "date",
                  "format": "dateOptionalTime",
                  "include_in_all": false
               },
               "scheduleDT": {
                  "type": "date",
                  "format": "dateOptionalTime",
                  "include_in_all": false
               },
               "title": {
                  "type": "string",
                  "fields": {
                     "english": {
                        "type": "string",
                        "analyzer": "english"
                     },
                     "raw": {
                        "type": "string",
                        "index": "not_analyzed"
                     },
                     "shingle": {
                        "type": "string",
                        "analyzer": "shingle"
                     },
                     "spanish": {
                        "type": "string",
                        "analyzer": "spanish"
                     }
                  },
                  "include_in_all": false
               }
            }
         }
      }
   }
}

我们使用 .NET 作为 ElasticSearch 的客户端,并且在为 scheduleDT 字段指定时区方面并不一致。

{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 12,
      "successful": 12,
      "failed": 0
   },
   "hits": {
      "total": 32,
      "max_score": null,
      "hits": [
         {
            "_index": "curator_v3",
            "_type": "published",
            "_id": "29651227",
            "_score": null,
            "fields": {
               "Id": [
                  "29651227"
               ],
               "scheduleDT": [
                  "2015-11-21T22:17:51.0946798-06:00"
               ],
               "title": [
                  "97 Year-Old Woman Cries Tears Of Joy After Finally Getting Her High School Diploma"
               ],
               "createDT": [
                  "2015-11-21T22:13:32.3597142-06:00"
               ]
            },
            "sort": [
               1448165871094
            ]
         },
         {
            "_index": "curator_v3",
            "_type": "published",
            "_id": "210466413",
            "_score": null,
            "fields": {
               "Id": [
                  "210466413"
               ],
               "scheduleDT": [
                  "2015-11-22T12:00:00"
               ],
               "title": [
                  "6 KC treats to bring to Thanksgiving"
               ],
               "createDT": [
                  "2015-11-20T15:08:25.4282-06:00"
               ]
            },
            "sort": [
               1448193600000
            ]
         }
      ]
   },
   "aggregations": {
      "ScheduleDT": {
         "doc_count_error_upper_bound": 0,
         "sum_other_doc_count": 27,
         "buckets": [
            {
               "key": 1448165871094,
               "key_as_string": "2015-11-22T04:17:51.094Z",
               "doc_count": 1
            },
            {
               "key": 1448193600000,
               "key_as_string": "2015-11-22T12:00:00.000Z",
               "doc_count": 4
            }
         ]
      }
   }
}

【问题讨论】:

    标签: date elasticsearch timezone


    【解决方案1】:

    您可以通过查询具有字段长度小于 20 个字符的 scheduleDT 的文档(例如 2015-11-22T12:00:00)来做到这一点。所有具有指定时区的日期字段都会更长。

    应该这样做:

    {
      "query": {
        "filtered": {
          "filter": {
            "script": {
              "script": "doc.scheduleDT.value.size() < 20"
            }
          }
        }
      }
    }
    

    但是,请注意,为了使您的查询更容易创建,您应该始终尝试在为您的文档编制索引之前将所有时间戳转换为 UTC。

    最后,还要确保您拥有dynamic scripting enabled 才能运行上述查询。

    更新

    实际上,如果您直接在脚本中使用_source,它将起作用,因为它将从源返回实际值,就像文档被索引时一样:

    {
      "query": {
        "filtered": {
          "filter": {
            "script": {
              "script": "_source.scheduleDT.size() < 20"
            }
          }
        }
      }
    }
    

    【讨论】:

    • Brillant Val。没有考虑将值视为字符串。我确实必须将您的脚本稍微更改为: doc.scheduleDT.value.toString().size()
    • 哦,你是对的,很抱歉,很高兴你明白了。
    • 我有足够的数据来转换,所以我没有立即注意到这一点,但与 20 个字符进行比较的“值”似乎是日期的底层表示(即 1448320714367)而不是字符串等价物(即 2015-11-23T17:18:34.367949-06:00) 我尝试了各种方法来返回结果中显示的相同字符串表示并使用它来检查长度 - 但还没有找到这样做的方法.
    • 这个脚本似乎更接近将日期表示为字符串 - 但无论日期最初是否有偏移,都始终将其格式化为 UTC。 new DateTime(doc.createDT.value).toString('yyyy-MM-dd HH:mm:ssZ')...日期2015-11-23T17 :18:34.367949-06:00 输出为 2015-11-23 23:18:34+0000 而日期 2014-10-15T15:35:03.34输出为 2014-10-15 15:35:03+0000.... 所以 ES 清楚地知道第一个日期有一个时区,而第二个没有。
    • 完美。非常感谢后续的 Val。
    猜你喜欢
    • 2021-09-29
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    相关资源
    最近更新 更多