Elasticsearch — получить конкретную дату локали в скрипте Groovy

#datetime #elasticsearch #groovy #inline

#дата и время #elasticsearch #groovy #встроенный

Вопрос:

Мне нужно обновить существующие документы определенного типа новым полем. Это новое поле должно быть установлено на название локального дня даты, заданной полем datetime в документе. Поле даты и времени имеет формат гггг-ММ-dd’T’HH: mm:ss, находится в UTC, но не имеет явного кода часового пояса.

Я бы хотел сделать это с помощью Groovy, но у меня нет опыта работы с Java. Я предполагаю, что мне нужно:

1) Установите для даты и времени значение UTC

2) Преобразовать в локальную локаль (в данном случае в Европу / Лондон)

3) Получите название дня из преобразованной даты и задайте с ним значение нового поля (dayname)

Если я использую следующий 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 — exact 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»

Комментарии:

1. какая версия Java работает под ним? 1.8?

2. Из того, что я вижу в документах, говорится, что Java 7 обновляет 55 или более позднюю версию

3. Да, так что это может быть Java 7 или 8… Для 8 есть более простой способ, чем для 7

4. JVM на узлах ES — 1.7.0_111, если это поможет? Я не знаю, но могу только предположить, что Goorvy будет использовать локальную JVM?

Ответ №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"))
  

Комментарии:

1. Спасибо! Это работает, если я удаляю часовой пояс из .parse и .format . Но сбой, если я оставляю часовой пояс с ошибкой: нет такого свойства: Часовой пояс для класса: 123322031df312eb7093fea2da1f852e31e1a660

2. Странно … попробуйте java.util.TimeZone.getTimeZone('UTC') и java.util.TimeZone.getTimeZone('Europe/London')

3. К сожалению, не повезло — я обновил свой вопрос выше. Спасибо за вашу помощь до сих пор!

Ответ №2:

Хорошо, немного больше исследований позволило мне понять, что ответ tim_yates был правильным, нам просто нужно было внести в белый список требуемый класс Java. Мы сделали это с помощью:

nano $JAVA_HOME/lib/security/java.policy

и добавление:

разрешение org.elasticsearch.script.ClassPermission «java.util.Часовой пояс»;

…затем перезапустите службы ES.

Обратите внимание, что этот класс выводится в белый список для всех пользователей, а не только для пользователя ES. См.:

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