| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 | [[modules-scripting]]== ScriptingThe scripting module allows to use scripts in order to evaluate customexpressions. For example, scripts can be used to return "script fields"as part of a search request, or can be used to evaluate a custom scorefor a query and so on.The scripting module uses by default http://mvel.codehaus.org/[mvel] asthe scripting language with some extensions. mvel is used since it isextremely fast and very simple to use, and in most cases, simpleexpressions are needed (for example, mathematical equations).Additional `lang` plugins are provided to allow to execute scripts indifferent languages. Currently supported plugins are `lang-javascript`for JavaScript, `lang-groovy` for Groovy, and `lang-python` for Python.All places where a `script` parameter can be used, a `lang` parameter(on the same level) can be provided to define the language of thescript. The `lang` options are `mvel`, `js`, `groovy`, `python`, and`native`.[float]=== Default Scripting LanguageThe default scripting language (assuming no `lang` parameter isprovided) is `mvel`. In order to change it set the `script.default_lang`to the appropriate language.[float]=== Preloaded ScriptsScripts can always be provided as part of the relevant API, but they canalso be preloaded by placing them under `config/scripts` and thenreferencing them by the script name (instead of providing the fullscript). This helps reduce the amount of data passed between the clientand the nodes.The name of the script is derived from the hierarchy of directories itexists under, and the file name without the lang extension. For example,a script placed under `config/scripts/group1/group2/test.py` will benamed `group1_group2_test`.[float]=== Native (Java) ScriptsEven though `mvel` is pretty fast, allow to register native Java basedscripts for faster execution.In order to allow for scripts, the `NativeScriptFactory` needs to beimplemented that constructs the script that will be executed. There aretwo main types, one that extends `AbstractExecutableScript` and one thatextends `AbstractSearchScript` (probably the one most users will extend,with additional helper classes in `AbstractLongSearchScript`,`AbstractDoubleSearchScript`, and `AbstractFloatSearchScript`).Registering them can either be done by settings, for example:`script.native.my.type` set to `sample.MyNativeScriptFactory` willregister 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 `lang` as `native`, andthe name of the script as the `script`.Note, the scripts need to be in the classpath of elasticsearch. Onesimple way to do it is to create a directory under plugins (choose adescriptive name), and place the jar / classes files there, they will beautomatically loaded.[float]=== ScoreIn all scripts that can be used in facets, allow to access the currentdoc score using `doc.score`.[float]=== Document FieldsMost scripting revolve around the use of specific document fields data.The `doc['field_name']` can be used to access specific field data withina document (the document in question is usually derived by the contextthe script is used). Document fields are very fast to access since theyend up being loaded into memory (all the relevant field values/tokensare loaded to memory).The following data can be extracted from a field:[cols="<,<",options="header",]|=======================================================================|Expression |Description|`doc['field_name'].value` |The native value of the field. For example,if its a short type, it will be short.|`doc['field_name'].values` |The native array values of the field. Forexample, if its a short type, it will be short[]. Remember, a field canhave several values within a single doc. Returns an empty array if thefield has no values.|`doc['field_name'].empty` |A boolean indicating if the field has novalues within the doc.|`doc['field_name'].multiValued` |A boolean indicating that the fieldhas several values within the corpus.|`doc['field_name'].lat` |The latitude of a geo point type.|`doc['field_name'].lon` |The longitude of a geo point type.|`doc['field_name'].lats` |The latitudes of a geo point type.|`doc['field_name'].lons` |The longitudes of a geo point type.|`doc['field_name'].distance(lat, lon)` |The `plane` distance (in miles)of this geo point field from the provided lat/lon.|`doc['field_name'].arcDistance(lat, lon)` |The `arc` distance (inmiles) of this geo point field from the provided lat/lon.|`doc['field_name'].distanceInKm(lat, lon)` |The `plane` distance (inkm) of this geo point field from the provided lat/lon.|`doc['field_name'].arcDistanceInKm(lat, lon)` |The `arc` distance (inkm) of this geo point field from the provided lat/lon.|`doc['field_name'].geohashDistance(geohash)` |The distance (in miles)of this geo point field from the provided geohash.|`doc['field_name'].geohashDistanceInKm(geohash)` |The distance (in km)of this geo point field from the provided geohash.|=======================================================================[float]=== Stored FieldsStored fields can also be accessed when executed a script. Note, theyare much slower to access compared with document fields, but are notloaded into memory. They can be simply accessed using`_fields['my_field_name'].value` or `_fields['my_field_name'].values`.[float]=== Source FieldThe source field can also be accessed when executing a script. Thesource field is loaded per doc, parsed, and then provided to the scriptfor evaluation. The `_source` forms the context under which the sourcefield can be accessed, for example `_source.obj2.obj1.field3`.[float]=== mvel Built In FunctionsThere are several built in functions that can be used within scripts.They include:[cols="<,<",options="header",]|=======================================================================|Function |Description|`time()` |The current time in milliseconds.|`sin(a)` |Returns the trigonometric sine of an angle.|`cos(a)` |Returns the trigonometric cosine of an angle.|`tan(a)` |Returns the trigonometric tangent of an angle.|`asin(a)` |Returns the arc sine of a value.|`acos(a)` |Returns the arc cosine of a value.|`atan(a)` |Returns the arc tangent of a value.|`toRadians(angdeg)` |Converts an angle measured in degrees to anapproximately equivalent angle measured in radians|`toDegrees(angrad)` |Converts an angle measured in radians to anapproximately equivalent angle measured in degrees.|`exp(a)` |Returns Euler's number _e_ raised to the power of value.|`log(a)` |Returns the natural logarithm (base _e_) of a value.|`log10(a)` |Returns the base 10 logarithm of a value.|`sqrt(a)` |Returns the correctly rounded positive square root of avalue.|`cbrt(a)` |Returns the cube root of a double value.|`IEEEremainder(f1, f2)` |Computes the remainder operation on twoarguments as prescribed by the IEEE 754 standard.|`ceil(a)` |Returns the smallest (closest to negative infinity) valuethat is greater than or equal to the argument and is equal to amathematical integer.|`floor(a)` |Returns the largest (closest to positive infinity) valuethat is less than or equal to the argument and is equal to amathematical integer.|`rint(a)` |Returns the value that is closest in value to the argumentand is equal to a mathematical integer.|`atan2(y, x)` |Returns the angle _theta_ from the conversion ofrectangular coordinates (_x_, _y_) to polar coordinates (r,_theta_).|`pow(a, b)` |Returns the value of the first argument raised to thepower of the second argument.|`round(a)` |Returns the closest _int_ to the argument.|`random()` |Returns a random _double_ value.|`abs(a)` |Returns the absolute value of a value.|`max(a, b)` |Returns the greater of two values.|`min(a, b)` |Returns the smaller of two values.|`ulp(d)` |Returns the size of an ulp of the argument.|`signum(d)` |Returns the signum function of the argument.|`sinh(x)` |Returns the hyperbolic sine of a value.|`cosh(x)` |Returns the hyperbolic cosine of a value.|`tanh(x)` |Returns the hyperbolic tangent of a value.|`hypot(x, y)` |Returns sqrt(_x2_ + _y2_) without intermediate overflowor underflow.|=======================================================================[float]=== Arithmetic precision in MVELWhen dividing two numbers using MVEL based scripts, the engine tries tobe smart and adheres to the default behaviour of java. This means if youdivide two integers (you might have configured the fields as integer inthe mapping), the result will also be an integer. This means, if acalculation like `1/num` is happening in your scripts and `num` is aninteger with the value of `8`, the result is `0` even though you wereexpecting it to be `0.125`. You may need to enforce precision byexplicitly using a double like `1.0/num` in order to get the expectedresult.
 |