【问题标题】:The datetime zone id 'america' is not recognised in Elasticasearch scriptElasticsearch 脚本中无法识别日期时区 ID“美国”
【发布时间】:2018-07-10 13:26:37
【问题描述】:

我有一个酒店位置的 Elasticsearch 索引,时区详细信息如下

{
"location":"1",
.
.
. 
"timezone": {
            "timeZoneName": "Eastern Daylight Time",
            "rawOffset": -18000,
            "timeZoneId": "America/New_York",
            "dstOffset": 3600,
            "status": "OK"
          }
}

我在 elasticsearch 脚本中使用这个时区详细信息来过滤文档。

def current_date = new Date(); 
def loc_date = current_date.setZone(org.joda.time.DateTimeZone.forID(doc['timezone.timeZoneId'].value)); 
def day=loc_date.format('EEEE').toString().toLowerCase();

当我在我的弹性搜索脚本 (Groovy) 中使用时区详细信息时,它会抛出错误

"type": "script_exception",
          "reason": "failed to run indexed script [uc-time-test38] using lang [groovy]",
          "caused_by": {
            "type": "illegal_argument_exception",
            "reason": "The datetime zone id 'america' is not recognised"
          }

看起来 doc['timezone.timeZoneId'].value 只返回 america 而不是 America/New_York

尝试将 doc['timezone.timeZoneId'].value 转换为字符串 doc['timezone.timeZoneId'].value.toString() 但问题仍然存在保持不变。

我的 Elasticsearch 版本是 2.3

当使用America/New_York搜索时,在索引中查询也不给出结果

下面的查询返回所有结果

   {
      "query": {
        "bool": {
          "must": {
            "term": {
              "timezone.timeZoneId": "america"
            }
          }
        }
      }
    }

但这给出了 0 结果

{
  "query": {
    "bool": {
      "must": {
        "term": {
          "timezone.timeZoneId": "America/New_York"
        }
      }
    }
  }
}

ES 映射

.
.
.
"timezone": {
        "properties": {
          "timeZoneName": {
            "type": "string"
          },
          "rawOffset": {
            "type": "long"
          },
          "timeZoneId": {
            "type": "string"
          },
          "dstOffset": {
            "type": "long"
          },
          "status": {
            "type": "string"
          }
        }
      },
.
.
.

【问题讨论】:

  • 好的,所以您认为您在文档中拥有的数据并不是您拥有的实际数据。你有什么问题?
  • 问题是为什么在我的时区 id 为“America/New_York”时抛出错误“无法识别日期时区 id 'america'”?
  • 如您所见,您在 doc['timezone.timeZoneId'].value 中没有时区 ID 为“America/New_York”。你所拥有的是“美国”。也许你在其他地方有正确的价值,但不是在 doc['timezone.timeZoneId'].value.
  • 我创建了另一个只有 5 条记录的索引,以便我可以手动检查没有时区 ID 为“美国”的记录。同样的错误抛出
  • 反斜杠是否可能是 elasticsearch 文档中的问题?就像我只得到第一部分,即字符串“America/New_York”的“america”,而不是完整的字符串“America/New_York”。

标签: elasticsearch groovy


【解决方案1】:
@Grab(group='joda-time', module='joda-time', version='2.9.9')
import org.joda.time.DateTimeZone

//this line prints America/New_York
println DateTimeZone.forID('America/New_York')

//this one throws exception
//java.lang.IllegalArgumentException: The datetime zone id 'America' is not recognised
println DateTimeZone.forID('America')

所以问题存在于您的数据中

【讨论】:

  • 我认为问题可能出在时区 ID 的存储上。反斜杠可能是弹性搜索文档中的问题吗?就像我只得到第一部分,即字符串“America/New_York”的“america”,而不是完整的字符串“America/New_York”。
  • 好的,只需输入一个常量 'America/New_York' 而不是 doc['timezone.timeZoneId'].value 并检查它是否工作
【解决方案2】:

解决了。问题在于保存的时区 ID。分析了 timeZoneId 字段,这就是为什么假设字符串 America/New_York 作为两个单独的关键字,AmericaNew_York

我做了什么

  • 备份旧索引
  • 使用新映射创建新索引,将 timeZoneId 字段设置为 not_analysed(关键字)
  • 将所有数据推送到新索引
  • 现在doc['timezone.timeZoneId'].value 在脚本中返回America/New_York

希望这可以帮助其他人。感谢讨论。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多