【问题标题】:Elasticsearch - Get locale specific date in Groovy scriptElasticsearch - 在 Groovy 脚本中获取特定于语言环境的日期
【发布时间】:2016-10-10 10:29:59
【问题描述】:

我需要使用新字段更新特定类型的现有文档。此新字段应设置为文档中日期时间字段给出的日期的本地日期名称。日期时间字段的格式为 yyyy-MM-dd'T'HH:mm:ss,采用 UTC 但没有明确的时区代码。

我想用 Groovy 做这件事,但没有 Java 经验。我猜我需要:

1) 将日期时间设置为 UTC 语言环境

2) 在这种情况下转换为本地语言环境(设置为欧洲/伦敦)

3) 从转换后的日期中获取日期名称并使用它设置新字段(日期名称)值

如果我使用以下 update_by_query:

POST /myindex/_update_by_query
{
  "script": {
    "inline": "ctx._source.dayname = Some_function(ctx._source.datetime)"
  },
  "query": {
    "term": {
      "_type": "myDocType"
    }
  }
}

有没有一种简单的方法可以使用一些 Groovy 函数(替换上面的 Some_function)。

任何提示将不胜感激!

更新 - 感谢 tim_yates 我有以下 Sense 控制台代码:

POST /rating/_update_by_query
{
  "script": {
    "inline": "ctx._source.day = Date.parse(\"yyyy-MM-dd'T'HH:mm:ss\", ctx._source.datetime, java.util.TimeZone.getTimeZone('UTC')).format('EEEE', java.util.TimeZone.getTimeZone('Europe/London'))"
  },
  "query": {
    "term": {
      "_type": "transaction"
    }
  }
}

不幸的是,这会产生以下错误消息:

{
   "error": {
      "root_cause": [
         {
            "type": "script_exception",
            "reason": "failed to run inline script [ctx._source.day = Date.parse(\"yyyy-MM-dd'T'HH:mm:ss\", ctx._source.datetime, java.util.TimeZone.getTimeZone('UTC')).format('EEEE', java.util.TimeZone.getTimeZone('Europe/London'))] using lang [groovy]"
         }
      ],
      "type": "script_exception",
      "reason": "failed to run inline script [ctx._source.day = Date.parse(\"yyyy-MM-dd'T'HH:mm:ss\", ctx._source.datetime, java.util.TimeZone.getTimeZone('UTC')).format('EEEE', java.util.TimeZone.getTimeZone('Europe/London'))] using lang [groovy]",
      "caused_by": {
         "type": "missing_property_exception",
         "reason": "No such property: java for class: 1209ff7fb16beac3a71ff2a276ac2225f7c4505b"
      }
   },
   "status": 500
}

虽然如果我删除对 getTimeZone 的引用它确实有效 - 确切的 Sense 控制台代码如下:

POST /rating/_update_by_query
{
  "script": {
    "inline": "ctx._source.day = Date.parse(\"yyyy-MM-dd'T'HH:mm:ss\", ctx._source.datetime).format('EEEE')"
  },
  "query": {
    "term": {
      "_type": "transaction"
    }
  }
}

我不确定为什么 getTimeZone 方法会失败。我试过“TimeZone.getTimeZone”而不是“java.util.TimeZone.getTimeZone”

【问题讨论】:

  • 下面运行的是哪个 Java 版本? 1.8?
  • 从我在文档中可以看到它说 Java 7 update 55 or later
  • 是的,所以它可能是 Java 7 或 8... 8 比 7 更简单
  • ES 节点上的 JVM 是 1.7.0_111 是否有帮助?我不知道,但只能假设 Goorvy 会使用本地 JVM?

标签: datetime elasticsearch groovy inline


【解决方案1】:

您需要的 Groovy 代码(用于 Java 7)将与此非常相似:

Date.parse("yyyy-MM-dd'T'HH:mm:ss", ctx._source.datetime, TimeZone.getTimeZone('UTC'))
    .format('EEEE', TimeZone.getTimeZone("Europe/London"))

【讨论】:

  • 谢谢!如果我从 .parse 和 .format 中删除 TimeZone,这将有效。但是如果我将 TimeZone 留在错误中会失败:没有这样的属性:TimeZone for class: 123322031df312eb7093fea2da1f852e31e1a660
  • 奇怪...试试java.util.TimeZone.getTimeZone('UTC')java.util.TimeZone.getTimeZone('Europe/London')
  • 不幸的是没有运气 - 我已经更新了我上面的问题。感谢您迄今为止的帮助!
【解决方案2】:

好的,更多的研究让我明白 tim_yates 的答案是正确的,我们只需要将所需的 Java 类列入白名单。我们通过以下方式做到这一点:

纳米 $JAVA_HOME/lib/security/java.policy

并添加:

权限 org.elasticsearch.script.ClassPermission "java.util.TimeZone";

...然后重启 ES 服务。

请注意,这会将所有用户的类列入白名单,而不仅仅是 ES 用户。见:

https://www.elastic.co/guide/en/elasticsearch/reference/2.2/modules-scripting-security.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-18
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2015-02-06
    • 2010-09-23
    相关资源
    最近更新 更多