2015-05-06 2 views
7

Каждый пример, который я видел (например, ElasticSearch: aggregation on _score field?), для выполнения агрегации в поле _score или связанного с ним, похоже, требует использования сценариев. Если по соображениям безопасности ElasticSearch отключает динамические сценарии по умолчанию, есть ли способ сделать это, не прибегая к загрузке файла сценария на каждый узел ES или повторное включение динамических сценариев?ElasticSearch: агрегация в поле _score w/Groovy отключена

Мой оригинальный агрегация выглядел следующим образом:

"aggs": { 
    "terms_agg": { 
     "terms": { 
      "field": "field1", 
      "order": {"max_score": "desc"} 
     }, 
    "aggs": { 
     "max_score": { 
      "max": {"script": "_score"} 
     }, 
     "top_terms": { 
      "top_hits": {"size": 1} 
     } 
     } 
} 

Попытка указать выражение, как языки, кажется, не работает, как ES выдает ошибку о том, счет можно получить только тогда, когда используется для сортировки. Я не могу понять какой-либо другой метод упорядочения моих ведер по полю оценки. У кого-нибудь есть идеи?

Редактировать: Чтобы уточнить, мое ограничение не в состоянии изменить серверную сторону. I.e., я не могу добавлять или редактировать что-либо как часть установки или конфигурации ES.

ответ

0

Одним из возможных подходов является использование других доступных сценариев. mvel кажется невозможным использовать, если динамический скриптинг не включен. И, если a more fine-grained control of scripting enable/disable не достигнет версии 1.6, я не думаю, что можно включить динамические скрипты для mvel, а не для groovy.

Осталось native и mustache (используется для шаблонов), которые включены по умолчанию. Я не думаю, что пользовательские сценарии могут быть выполнены с помощью mustache, если это возможно, я не нашел пути, и мы остаемся с помощью скриптов native (Java).

Вот мой взять на это:

  • создать реализацию NativeScriptFactory:
package com.foo.script; 

import java.util.Map; 

import org.elasticsearch.script.ExecutableScript; 
import org.elasticsearch.script.NativeScriptFactory; 

public class MyScriptNativeScriptFactory implements NativeScriptFactory { 

    @Override 
    public ExecutableScript newScript(Map<String, Object> arg0) { 
     return new MyScript(); 
    } 

} 
  • реализация AbstractFloatSearchScript, например:
package com.foo.script; 

import java.io.IOException; 

import org.elasticsearch.script.AbstractFloatSearchScript; 

public class MyScript extends AbstractFloatSearchScript { 

    @Override 
    public float runAsFloat() { 
     try { 
      return score(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return 0; 
    } 

} 
  • альтернативно, построить простой Maven проект, чтобы связать все вместе. pom.xml:
<properties> 
    <elasticsearch.version>1.5.2</elasticsearch.version> 
    <maven.compiler.source>1.8</maven.compiler.source> 
    <maven.compiler.target>1.8</maven.compiler.target> 
</properties> 

<dependencies> 
    <dependency> 
     <groupId>org.elasticsearch</groupId> 
     <artifactId>elasticsearch</artifactId> 
     <version>${elasticsearch.version}</version> 
     <scope>compile</scope> 
    </dependency> 
</dependencies> 

<build> 
    <sourceDirectory>src</sourceDirectory> 
    <plugins> 
     <plugin> 
      <artifactId>maven-compiler-plugin</artifactId> 
      <version>3.1</version> 
      <configuration> 
       <source>1.8</source> 
       <target>1.8</target> 
      </configuration> 
     </plugin> 
    </plugins> 
</build> 
  • построить его и получить результирующий файл банку.
  • место банку внутри [ES_folder]/Библиотека
  • редактировать elasticsearch.yml и добавить script.native.my_script.type: com.foo.script.MyScriptNativeScriptFactory

  • перезапуска ES узлов.

  • использовать его в агрегатах:
{ 
    "aggs": { 
    "max_score": { 
     "max": { 
     "script": "my_script", 
     "lang": "native" 
     } 
    } 
    } 
} 

Мой образец выше просто возвращает _score как сценарий, но, конечно, он может быть использован в более сложных сценариях.

EDIT: если вам не разрешено касаться экземпляров, то я не думаю, что у вас есть какие-либо опции.

+0

К сожалению, это не идеальное решение. Кроме того, было бы намного проще просто написать groovy-скрипт и поместить его в /scripts /. Например, в моем случае я мог бы написать '_score' в файле с именем _score.groovy и поместить его в скрипты /, и он будет автоматически выбран ES. Из моего тестирования мне даже не пришлось бы менять сценарий '{" script ":" _score "}' для использования "script_file", он просто сработает. Проблема в том, что это решение требует прямого доступа для изменения узлов, что я не могу гарантировать. – user4872035

+0

Я дал вам альтернативу, единственное возможное, на мой взгляд, с учетом ваших ограничений. Вы сказали, что не хотите использовать Groovy (из-за динамического сценария) и не хотите «загружать файл сценария на каждый узел ES или повторно активировать динамический скриптинг». Если вы вместо этого хотите использовать файлы сценариев, то да - проще, но вы сказали, что не хотите этого делать. Если вы сохраните свои первоначальные ограничения, я не думаю, что есть другой способ, чем сценарий «native». Приветствия. –

+0

Ах, тогда я думаю, что мои ограничения были недостаточно ясными, так как ваша альтернатива попадает в это ведро (каламбур не предназначен). Мое ограничение - это кластер ES, в котором я не контролирую и не могу изменить конфигурацию. Я отредактирую сообщение, чтобы уточнить. Благодаря! – user4872035

0

ElasticSearch по крайней мере версии 1.7.1 и, возможно, ранее также предлагает использование языка сценариев выражения Expression Lucene, а по умолчанию это изолированная песочница может использоваться для динамических встроенных скриптов почти так же, как Groovy. В нашем случае, когда наш производственный кластер ES только что был повышен с 1.4.1 до 1.7.1, мы решили больше не использовать Groovy из-за его небедсодержащей природы, хотя мы по-прежнему хотим использовать динамические скрипты из-за легкость развертывания и гибкость, которую они предлагают, поскольку мы продолжаем точно настраивать наше приложение и его слой поиска.

При написании собственного сценария Java в качестве замены наших динамических значений функции Groovy, возможно, также была возможность в нашем случае, мы хотели бы рассмотреть возможность использования выражения для нашего динамического встроенного языка сценариев. Прочитав документацию, я обнаружил, что мы просто смогли изменить атрибут «lang» от "groovy" до "expression" в наших встроенных сценариях function_score и с помощью свойства script.inline: sandbox, установленного в файле .../config/elasticsearch.yml. Скрипт счетчика функций работал без каких-либо изменений. Таким образом, теперь мы можем продолжать использовать динамические встроенные скрипты в ElasticSearch, и делать это с поддержкой песочницы (поскольку Expression изолирован по умолчанию). Очевидно, что другие меры безопасности, такие как запуск вашего ES-кластера за прокси-сервером приложений и брандмауэром, также должны быть реализованы для обеспечения того, чтобы внешние пользователи не имели прямого доступа к вашим узлам ES или ES API. Однако это было очень простое изменение, которое на данный момент решило проблему с отсутствием Groovy песочницы и проблемами, позволяющими ему работать без песочницы.

При переключении динамических скриптов на выражение может работать или быть применимым в некоторых случаях (в зависимости от сложности встроенных динамических скриптов), казалось бы, стоит поделиться этой информацией в надежде, что это может помочь другим разработчикам.

В качестве одного примечания, один из других поддерживаемых языков сценариев ES, Mustache, по-видимому, можно использовать для создания шаблонов в ваших поисковых запросах. Похоже, что он не подходит для любых более сложных задач сценариев, таких как function_score и т. Д., Хотя я не уверен, что это было совершенно очевидно во время первого ознакомления с обновленной документацией ES.

Наконец, еще один вопрос, который будет помнить о том, что использование скриптов Expression Lucene отмечены как экспериментальной функции в последней версии ES и документация отмечает, что, как это расширение сценариев претерпевает значительные работы по развитию в этом время, его использование или функциональность могут измениться в более поздних версиях ES. Таким образом, если вы переключитесь на использование выражения для любого из ваших сценариев (динамического или иного), в примечаниях к документации/разработчику следует обратить внимание на повторное ознакомление с этими изменениями, прежде чем обновлять вашу установку ES в следующий раз, чтобы убедиться, что ваши скрипты остаются совместимыми и работают как ожидается.

Для нашей ситуации по крайней мере, если только мы не захотели разрешить динамические сценарии без песочницы снова включить в последней версии ES (через опцию script.inline: on), чтобы встроенные скрипты Groovy могли продолжать работать, переключаясь на В настоящее время сценарий Lucene Expression выглядит как лучший вариант.

Будет интересно узнать, какие изменения произошли при выборе сценариев для ES в будущих выпусках, особенно если учесть, что опция (по-видимому, неэффективная) песочницы для Groovy будет полностью удалена версией 2.0. Надеемся, что другие возможности защиты могут быть использованы для динамического использования Groovy, или, возможно, сценарии Lucene Expression займут место Groovy и позволят использовать все типы динамических сценариев, которые разработчики уже используют.

Для получения дополнительной информации о выражении Lucene см. Документацию ES здесь: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html#_lucene_expressions_scripts - эта страница также является источником примечания о планируемом удалении опции песочницы Groovy из ES v2.0 +. Дальнейшую документацию Lucene Expression можно найти здесь: http://lucene.apache.org/core/4_9_0/expressions/index.html?org/apache/lucene/expressions/js/package-summary.html

Смежные вопросы