The scripting module allows to use scripts in order to evaluate custom expressions. For example, scripts can be used to return "script fields" as part of a search request, or can be used to evaluate a custom score for a query and so on.
The scripting module uses by default mvel as the scripting language with some extensions. mvel is used since it is extremely fast and very simple to use, and in most cases, simple expressions are needed (for example, mathematical equations).
lang plugins are provided to allow to execute scripts in
different languages. Currently supported plugins are
lang-groovy for Groovy, and
lang-python for Python.
All places where a
script parameter can be used, a
(on the same level) can be provided to define the language of the
lang options are
Default Scripting Languageedit
The default scripting language (assuming no
lang parameter is
mvel. In order to change it set the
to the appropriate language.
Scripts can always be provided as part of the relevant API, but they can
also be preloaded by placing them under
config/scripts and then
referencing them by the script name (instead of providing the full
script). This helps reduce the amount of data passed between the client
and the nodes.
The name of the script is derived from the hierarchy of directories it
exists under, and the file name without the lang extension. For example,
a script placed under
config/scripts/group1/group2/test.py will be
Disabling dynamic scriptsedit
We recommend running Elasticsearch behind an application or proxy, which protects Elasticsearch from the outside world. If users are allowed to run dynamic scripts (even in a search request), then they have the same access to your box as the user that Elasticsearch is running as.
First, you should not run Elasticsearch as the
root user, as this
would allow a script to access or do anything on your server, without
limitations. Second, you should not expose Elasticsearch directly to
users, but instead have a proxy application inbetween. If you do
intend to expose Elasticsearch directly to your users, then you have
to decide whether you trust them enough to run scripts on your box or
not. If not, then even if you have a proxy which only allows
requests, you should disable dynamic scripting by adding the following
setting to the
config/elasticsearch.yml file on every node:
This will still allow execution of named scripts provided in the config, or native Java scripts registered through plugins, however it will prevent users from running arbitrary scripts via the API.
Automatic Script Reloadingedit
Added in 0.90.6.
config/scripts directory is scanned periodically for changes.
New and changed scripts are reloaded and deleted script are removed
from preloaded scripts cache. The reload frequency can be specified
watcher.interval setting, which defaults to
To disable script reloading completely set
Native (Java) Scriptsedit
mvel is pretty fast, allow to register native Java based
scripts for faster execution.
In order to allow for scripts, the
NativeScriptFactory needs to be
implemented that constructs the script that will be executed. There are
two main types, one that extends
AbstractExecutableScript and one that
AbstractSearchScript (probably the one most users will extend,
with additional helper classes in
Registering them can either be done by settings, for example:
script.native.my.type set to
register a script named
my. Another option is in a plugin, access
ScriptModule and call
registerScript on it.
Executing the script is done by specifying the
the name of the script as the
Note, the scripts need to be in the classpath of elasticsearch. One simple way to do it is to create a directory under plugins (choose a descriptive name), and place the jar / classes files there, they will be automatically loaded.
In all scripts that can be used in facets, allow to access the current
doc score using
Computing scores based on terms in scriptsedit
Most scripting revolve around the use of specific document fields data.
doc['field_name'] can be used to access specific field data within
a document (the document in question is usually derived by the context
the script is used). Document fields are very fast to access since they
end up being loaded into memory (all the relevant field values/tokens
are loaded to memory).
The following data can be extracted from a field:
The native value of the field. For example, if its a short type, it will be short.
The native array values of the field. For example, if its a short type, it will be short. Remember, a field can have several values within a single doc. Returns an empty array if the field has no values.
A boolean indicating if the field has no values within the doc.
A boolean indicating that the field has several values within the corpus.
The latitude of a geo point type.
The longitude of a geo point type.
The latitudes of a geo point type.
The longitudes of a geo point type.
The distance (in miles) of this geo point field from the provided geohash.
The distance (in km) of this geo point field from the provided geohash.
Stored fields can also be accessed when executed a script. Note, they
are much slower to access compared with document fields, but are not
loaded into memory. They can be simply accessed using
The source field can also be accessed when executing a script. The
source field is loaded per doc, parsed, and then provided to the script
for evaluation. The
_source forms the context under which the source
field can be accessed, for example
_source is much slower compared to using
but the data is not loaded into memory. For a single field access
_fields may be
faster than using
_source due to the extra overhead of potentially parsing large documents.
_source may be faster if you access multiple fields or if the source has already been
loaded for other purposes.
mvel Built In Functionsedit
There are several built in functions that can be used within scripts. They include:
The current time in milliseconds.
Returns the trigonometric sine of an angle.
Returns the trigonometric cosine of an angle.
Returns the trigonometric tangent of an angle.
Returns the arc sine of a value.
Returns the arc cosine of a value.
Returns the arc tangent of a value.
Converts an angle measured in degrees to an approximately equivalent angle measured in radians
Converts an angle measured in radians to an approximately equivalent angle measured in degrees.
Returns Euler’s number e raised to the power of value.
Returns the natural logarithm (base e) of a value.
Returns the base 10 logarithm of a value.
Returns the correctly rounded positive square root of a value.
Returns the cube root of a double value.
Computes the remainder operation on two arguments as prescribed by the IEEE 754 standard.
Returns the smallest (closest to negative infinity) value that is greater than or equal to the argument and is equal to a mathematical integer.
Returns the largest (closest to positive infinity) value that is less than or equal to the argument and is equal to a mathematical integer.
Returns the value that is closest in value to the argument and is equal to a mathematical integer.
Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r,theta).
Returns the value of the first argument raised to the power of the second argument.
Returns the closest int to the argument.
Returns a random double value.
Returns the absolute value of a value.
Returns the greater of two values.
Returns the smaller of two values.
Returns the size of an ulp of the argument.
Returns the signum function of the argument.
Returns the hyperbolic sine of a value.
Returns the hyperbolic cosine of a value.
Returns the hyperbolic tangent of a value.
Returns sqrt(x2 + y2) without intermediate overflow or underflow.
Arithmetic precision in MVELedit
When dividing two numbers using MVEL based scripts, the engine tries to
be smart and adheres to the default behaviour of java. This means if you
divide two integers (you might have configured the fields as integer in
the mapping), the result will also be an integer. This means, if a
1/num is happening in your scripts and
num is an
integer with the value of
8, the result is
0 even though you were
expecting it to be
0.125. You may need to enforce precision by
explicitly using a double like
1.0/num in order to get the expected