scripting.asciidoc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. [[modules-scripting]]
  2. == Scripting
  3. The scripting module allows to use scripts in order to evaluate custom
  4. expressions. For example, scripts can be used to return "script fields"
  5. as part of a search request, or can be used to evaluate a custom score
  6. for a query and so on.
  7. The scripting module uses by default http://mvel.codehaus.org/[mvel] as
  8. the scripting language with some extensions. mvel is used since it is
  9. extremely fast and very simple to use, and in most cases, simple
  10. expressions are needed (for example, mathematical equations).
  11. Additional `lang` plugins are provided to allow to execute scripts in
  12. different languages. Currently supported plugins are `lang-javascript`
  13. for JavaScript, `lang-groovy` for Groovy, and `lang-python` for Python.
  14. All places where a `script` parameter can be used, a `lang` parameter
  15. (on the same level) can be provided to define the language of the
  16. script. The `lang` options are `mvel`, `js`, `groovy`, `python`, and
  17. `native`.
  18. [float]
  19. === Default Scripting Language
  20. The default scripting language (assuming no `lang` parameter is
  21. provided) is `mvel`. In order to change it set the `script.default_lang`
  22. to the appropriate language.
  23. [float]
  24. === Preloaded Scripts
  25. Scripts can always be provided as part of the relevant API, but they can
  26. also be preloaded by placing them under `config/scripts` and then
  27. referencing them by the script name (instead of providing the full
  28. script). This helps reduce the amount of data passed between the client
  29. and the nodes.
  30. The name of the script is derived from the hierarchy of directories it
  31. exists under, and the file name without the lang extension. For example,
  32. a script placed under `config/scripts/group1/group2/test.py` will be
  33. named `group1_group2_test`.
  34. [float]
  35. === Native (Java) Scripts
  36. Even though `mvel` is pretty fast, allow to register native Java based
  37. scripts for faster execution.
  38. In order to allow for scripts, the `NativeScriptFactory` needs to be
  39. implemented that constructs the script that will be executed. There are
  40. two main types, one that extends `AbstractExecutableScript` and one that
  41. extends `AbstractSearchScript` (probably the one most users will extend,
  42. with additional helper classes in `AbstractLongSearchScript`,
  43. `AbstractDoubleSearchScript`, and `AbstractFloatSearchScript`).
  44. Registering them can either be done by settings, for example:
  45. `script.native.my.type` set to `sample.MyNativeScriptFactory` will
  46. register a script named `my`. Another option is in a plugin, access
  47. `ScriptModule` and call `registerScript` on it.
  48. Executing the script is done by specifying the `lang` as `native`, and
  49. the name of the script as the `script`.
  50. Note, the scripts need to be in the classpath of elasticsearch. One
  51. simple way to do it is to create a directory under plugins (choose a
  52. descriptive name), and place the jar / classes files there, they will be
  53. automatically loaded.
  54. [float]
  55. === Score
  56. In all scripts that can be used in facets, allow to access the current
  57. doc score using `doc.score`.
  58. [float]
  59. === Document Fields
  60. Most scripting revolve around the use of specific document fields data.
  61. The `doc['field_name']` can be used to access specific field data within
  62. a document (the document in question is usually derived by the context
  63. the script is used). Document fields are very fast to access since they
  64. end up being loaded into memory (all the relevant field values/tokens
  65. are loaded to memory).
  66. The following data can be extracted from a field:
  67. [cols="<,<",options="header",]
  68. |=======================================================================
  69. |Expression |Description
  70. |`doc['field_name'].value` |The native value of the field. For example,
  71. if its a short type, it will be short.
  72. |`doc['field_name'].values` |The native array values of the field. For
  73. example, if its a short type, it will be short[]. Remember, a field can
  74. have several values within a single doc. Returns an empty array if the
  75. field has no values.
  76. |`doc['field_name'].empty` |A boolean indicating if the field has no
  77. values within the doc.
  78. |`doc['field_name'].multiValued` |A boolean indicating that the field
  79. has several values within the corpus.
  80. |`doc['field_name'].lat` |The latitude of a geo point type.
  81. |`doc['field_name'].lon` |The longitude of a geo point type.
  82. |`doc['field_name'].lats` |The latitudes of a geo point type.
  83. |`doc['field_name'].lons` |The longitudes of a geo point type.
  84. |`doc['field_name'].distance(lat, lon)` |The `plane` distance (in miles)
  85. of this geo point field from the provided lat/lon.
  86. |`doc['field_name'].arcDistance(lat, lon)` |The `arc` distance (in
  87. miles) of this geo point field from the provided lat/lon.
  88. |`doc['field_name'].distanceInKm(lat, lon)` |The `plane` distance (in
  89. km) of this geo point field from the provided lat/lon.
  90. |`doc['field_name'].arcDistanceInKm(lat, lon)` |The `arc` distance (in
  91. km) of this geo point field from the provided lat/lon.
  92. |`doc['field_name'].geohashDistance(geohash)` |The distance (in miles)
  93. of this geo point field from the provided geohash.
  94. |`doc['field_name'].geohashDistanceInKm(geohash)` |The distance (in km)
  95. of this geo point field from the provided geohash.
  96. |=======================================================================
  97. [float]
  98. === Stored Fields
  99. Stored fields can also be accessed when executed a script. Note, they
  100. are much slower to access compared with document fields, but are not
  101. loaded into memory. They can be simply accessed using
  102. `_fields['my_field_name'].value` or `_fields['my_field_name'].values`.
  103. [float]
  104. === Source Field
  105. The source field can also be accessed when executing a script. The
  106. source field is loaded per doc, parsed, and then provided to the script
  107. for evaluation. The `_source` forms the context under which the source
  108. field can be accessed, for example `_source.obj2.obj1.field3`.
  109. [float]
  110. === mvel Built In Functions
  111. There are several built in functions that can be used within scripts.
  112. They include:
  113. [cols="<,<",options="header",]
  114. |=======================================================================
  115. |Function |Description
  116. |`time()` |The current time in milliseconds.
  117. |`sin(a)` |Returns the trigonometric sine of an angle.
  118. |`cos(a)` |Returns the trigonometric cosine of an angle.
  119. |`tan(a)` |Returns the trigonometric tangent of an angle.
  120. |`asin(a)` |Returns the arc sine of a value.
  121. |`acos(a)` |Returns the arc cosine of a value.
  122. |`atan(a)` |Returns the arc tangent of a value.
  123. |`toRadians(angdeg)` |Converts an angle measured in degrees to an
  124. approximately equivalent angle measured in radians
  125. |`toDegrees(angrad)` |Converts an angle measured in radians to an
  126. approximately equivalent angle measured in degrees.
  127. |`exp(a)` |Returns Euler's number _e_ raised to the power of value.
  128. |`log(a)` |Returns the natural logarithm (base _e_) of a value.
  129. |`log10(a)` |Returns the base 10 logarithm of a value.
  130. |`sqrt(a)` |Returns the correctly rounded positive square root of a
  131. value.
  132. |`cbrt(a)` |Returns the cube root of a double value.
  133. |`IEEEremainder(f1, f2)` |Computes the remainder operation on two
  134. arguments as prescribed by the IEEE 754 standard.
  135. |`ceil(a)` |Returns the smallest (closest to negative infinity) value
  136. that is greater than or equal to the argument and is equal to a
  137. mathematical integer.
  138. |`floor(a)` |Returns the largest (closest to positive infinity) value
  139. that is less than or equal to the argument and is equal to a
  140. mathematical integer.
  141. |`rint(a)` |Returns the value that is closest in value to the argument
  142. and is equal to a mathematical integer.
  143. |`atan2(y, x)` |Returns the angle _theta_ from the conversion of
  144. rectangular coordinates (_x_, _y_) to polar coordinates (r,_theta_).
  145. |`pow(a, b)` |Returns the value of the first argument raised to the
  146. power of the second argument.
  147. |`round(a)` |Returns the closest _int_ to the argument.
  148. |`random()` |Returns a random _double_ value.
  149. |`abs(a)` |Returns the absolute value of a value.
  150. |`max(a, b)` |Returns the greater of two values.
  151. |`min(a, b)` |Returns the smaller of two values.
  152. |`ulp(d)` |Returns the size of an ulp of the argument.
  153. |`signum(d)` |Returns the signum function of the argument.
  154. |`sinh(x)` |Returns the hyperbolic sine of a value.
  155. |`cosh(x)` |Returns the hyperbolic cosine of a value.
  156. |`tanh(x)` |Returns the hyperbolic tangent of a value.
  157. |`hypot(x, y)` |Returns sqrt(_x2_ + _y2_) without intermediate overflow
  158. or underflow.
  159. |=======================================================================
  160. [float]
  161. === Arithmetic precision in MVEL
  162. When dividing two numbers using MVEL based scripts, the engine tries to
  163. be smart and adheres to the default behaviour of java. This means if you
  164. divide two integers (you might have configured the fields as integer in
  165. the mapping), the result will also be an integer. This means, if a
  166. calculation like `1/num` is happening in your scripts and `num` is an
  167. integer with the value of `8`, the result is `0` even though you were
  168. expecting it to be `0.125`. You may need to enforce precision by
  169. explicitly using a double like `1.0/num` in order to get the expected
  170. result.