scripting.asciidoc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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. deprecated[1.3.0,Groovy has replaced Mvel as the default scripting language]
  8. The scripting module uses by default http://groovy.codehaus.org/[groovy]
  9. (previously http://mvel.codehaus.org/[mvel]) as the scripting language with some
  10. extensions. Groovy is used since it is extremely fast and very simple to use.
  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-mvel` for Mvel, 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 `groovy`, `js`, `mvel`, `python`, and
  17. `native`.
  18. added[1.2.0, Dynamic scripting is disabled for non-sandboxed languages by default since version 1.2.0]
  19. To increase security, Elasticsearch does not allow you to specify scripts for
  20. non-sandboxed languages with a request. Instead, scripts must be placed in the
  21. `scripts` directory inside the configuration directory (the directory where
  22. elasticsearch.yml is). Scripts placed into this directory will automatically be
  23. picked up and be available to be used. Once a script has been placed in this
  24. directory, it can be referenced by name. For example, a script called
  25. `calculate-score.groovy` can be referenced in a request like this:
  26. [source,sh]
  27. --------------------------------------------------
  28. $ tree config
  29. config
  30. ├── elasticsearch.yml
  31. ├── logging.yml
  32. └── scripts
  33. └── calculate-score.groovy
  34. --------------------------------------------------
  35. [source,sh]
  36. --------------------------------------------------
  37. $ cat config/scripts/calculate-score.groovy
  38. log(_score * 2) + my_modifier
  39. --------------------------------------------------
  40. [source,js]
  41. --------------------------------------------------
  42. curl -XPOST localhost:9200/_search -d '{
  43. "query": {
  44. "function_score": {
  45. "query": {
  46. "match": {
  47. "body": "foo"
  48. }
  49. },
  50. "functions": [
  51. {
  52. "script_score": {
  53. "script": "calculate-score",
  54. "params": {
  55. "my_modifier": 8
  56. }
  57. }
  58. }
  59. ]
  60. }
  61. }
  62. }'
  63. --------------------------------------------------
  64. The name of the script is derived from the hierarchy of directories it
  65. exists under, and the file name without the lang extension. For example,
  66. a script placed under `config/scripts/group1/group2/test.py` will be
  67. named `group1_group2_test`.
  68. [float]
  69. === Enabling dynamic scripting
  70. We recommend running Elasticsearch behind an application or proxy, which
  71. protects Elasticsearch from the outside world. If users are allowed to run
  72. dynamic scripts (even in a search request), then they have the same access to
  73. your box as the user that Elasticsearch is running as. For this reason dynamic
  74. scripting is allowed only for sandboxed languages by default.
  75. First, you should not run Elasticsearch as the `root` user, as this would allow
  76. a script to access or do *anything* on your server, without limitations. Second,
  77. you should not expose Elasticsearch directly to users, but instead have a proxy
  78. application inbetween. If you *do* intend to expose Elasticsearch directly to
  79. your users, then you have to decide whether you trust them enough to run scripts
  80. on your box or not. If you do, you can enable dynamic scripting by adding the
  81. following setting to the `config/elasticsearch.yml` file on every node:
  82. [source,yaml]
  83. -----------------------------------
  84. script.disable_dynamic: false
  85. -----------------------------------
  86. While this still allows execution of named scripts provided in the config, or
  87. _native_ Java scripts registered through plugins, it also allows users to run
  88. arbitrary scripts via the API. Instead of sending the name of the file as the
  89. script, the body of the script can be sent instead.
  90. There are three possible configuration values for the `script.disable_dynamic`
  91. setting, the default value is `sandbox`:
  92. [cols="<,<",options="header",]
  93. |=======================================================================
  94. |Value |Description
  95. | `true` |all dynamic scripting is disabled, scripts must be placed in the `config/scripts` directory.
  96. | `false` |all dynamic scripting is enabled, scripts may be sent as strings in requests.
  97. | `sandbox` |scripts may be sent as strings for languages that are sandboxed.
  98. |=======================================================================
  99. [float]
  100. === Default Scripting Language
  101. The default scripting language (assuming no `lang` parameter is provided) is
  102. `groovy`. In order to change it, set the `script.default_lang` to the
  103. appropriate language.
  104. [float]
  105. === Groovy Sandboxing
  106. Elasticsearch sandboxes Groovy scripts that are compiled and executed in order
  107. to ensure they don't perform unwanted actions. There are a number of options
  108. that can be used for configuring this sandbox:
  109. `script.groovy.sandbox.receiver_whitelist`::
  110. Comma-separated list of string classes for objects that may have methods
  111. invoked.
  112. `script.groovy.sandbox.package_whitelist`::
  113. Comma-separated list of packages under which new objects may be constructed.
  114. `script.groovy.sandbox.class_whitelist`::
  115. Comma-separated list of classes that are allowed to be constructed.
  116. `script.groovy.sandbox.method_blacklist`::
  117. Comma-separated list of methods that are never allowed to be invoked,
  118. regardless of target object.
  119. `script.groovy.sandbox.enabled`::
  120. Flag to disable the sandbox (defaults to `true` meaning the sandbox is
  121. enabled).
  122. [float]
  123. === Automatic Script Reloading
  124. The `config/scripts` directory is scanned periodically for changes.
  125. New and changed scripts are reloaded and deleted script are removed
  126. from preloaded scripts cache. The reload frequency can be specified
  127. using `watcher.interval` setting, which defaults to `60s`.
  128. To disable script reloading completely set `script.auto_reload_enabled`
  129. to `false`.
  130. [float]
  131. === Native (Java) Scripts
  132. Even though `groovy` is pretty fast, this allows to register native Java based
  133. scripts for faster execution.
  134. In order to allow for scripts, the `NativeScriptFactory` needs to be
  135. implemented that constructs the script that will be executed. There are
  136. two main types, one that extends `AbstractExecutableScript` and one that
  137. extends `AbstractSearchScript` (probably the one most users will extend,
  138. with additional helper classes in `AbstractLongSearchScript`,
  139. `AbstractDoubleSearchScript`, and `AbstractFloatSearchScript`).
  140. Registering them can either be done by settings, for example:
  141. `script.native.my.type` set to `sample.MyNativeScriptFactory` will
  142. register a script named `my`. Another option is in a plugin, access
  143. `ScriptModule` and call `registerScript` on it.
  144. Executing the script is done by specifying the `lang` as `native`, and
  145. the name of the script as the `script`.
  146. Note, the scripts need to be in the classpath of elasticsearch. One
  147. simple way to do it is to create a directory under plugins (choose a
  148. descriptive name), and place the jar / classes files there, they will be
  149. automatically loaded.
  150. [float]
  151. === Score
  152. In all scripts that can be used in facets, allow to access the current
  153. doc score using `doc.score`.
  154. [float]
  155. === Computing scores based on terms in scripts
  156. see <<modules-advanced-scripting, advanced scripting documentation>>
  157. [float]
  158. === Document Fields
  159. Most scripting revolve around the use of specific document fields data.
  160. The `doc['field_name']` can be used to access specific field data within
  161. a document (the document in question is usually derived by the context
  162. the script is used). Document fields are very fast to access since they
  163. end up being loaded into memory (all the relevant field values/tokens
  164. are loaded to memory).
  165. The following data can be extracted from a field:
  166. [cols="<,<",options="header",]
  167. |=======================================================================
  168. |Expression |Description
  169. |`doc['field_name'].value` |The native value of the field. For example,
  170. if its a short type, it will be short.
  171. |`doc['field_name'].values` |The native array values of the field. For
  172. example, if its a short type, it will be short[]. Remember, a field can
  173. have several values within a single doc. Returns an empty array if the
  174. field has no values.
  175. |`doc['field_name'].empty` |A boolean indicating if the field has no
  176. values within the doc.
  177. |`doc['field_name'].multiValued` |A boolean indicating that the field
  178. has several values within the corpus.
  179. |`doc['field_name'].lat` |The latitude of a geo point type.
  180. |`doc['field_name'].lon` |The longitude of a geo point type.
  181. |`doc['field_name'].lats` |The latitudes of a geo point type.
  182. |`doc['field_name'].lons` |The longitudes of a geo point type.
  183. |`doc['field_name'].distance(lat, lon)` |The `plane` distance (in meters)
  184. of this geo point field from the provided lat/lon.
  185. |`doc['field_name'].distanceWithDefault(lat, lon, default)` |The `plane` distance (in meters)
  186. of this geo point field from the provided lat/lon with a default value.
  187. |`doc['field_name'].distanceInMiles(lat, lon)` |The `plane` distance (in
  188. miles) of this geo point field from the provided lat/lon.
  189. |`doc['field_name'].distanceInMilesWithDefault(lat, lon, default)` |The `plane` distance (in
  190. miles) of this geo point field from the provided lat/lon with a default value.
  191. |`doc['field_name'].distanceInKm(lat, lon)` |The `plane` distance (in
  192. km) of this geo point field from the provided lat/lon.
  193. |`doc['field_name'].distanceInKmWithDefault(lat, lon, default)` |The `plane` distance (in
  194. km) of this geo point field from the provided lat/lon with a default value.
  195. |`doc['field_name'].arcDistance(lat, lon)` |The `arc` distance (in
  196. meters) of this geo point field from the provided lat/lon.
  197. |`doc['field_name'].arcDistanceWithDefault(lat, lon, default)` |The `arc` distance (in
  198. meters) of this geo point field from the provided lat/lon with a default value.
  199. |`doc['field_name'].arcDistanceInMiles(lat, lon)` |The `arc` distance (in
  200. miles) of this geo point field from the provided lat/lon.
  201. |`doc['field_name'].arcDistanceInMilesWithDefault(lat, lon, default)` |The `arc` distance (in
  202. miles) of this geo point field from the provided lat/lon with a default value.
  203. |`doc['field_name'].arcDistanceInKm(lat, lon)` |The `arc` distance (in
  204. km) of this geo point field from the provided lat/lon.
  205. |`doc['field_name'].arcDistanceInKmWithDefault(lat, lon, default)` |The `arc` distance (in
  206. km) of this geo point field from the provided lat/lon with a default value.
  207. |`doc['field_name'].factorDistance(lat, lon)` |The distance factor of this geo point field from the provided lat/lon.
  208. |`doc['field_name'].factorDistance(lat, lon, default)` |The distance factor of this geo point field from the provided lat/lon with a default value.
  209. |`doc['field_name'].geohashDistance(geohash)` |The `arc` distance (in meters)
  210. of this geo point field from the provided geohash.
  211. |`doc['field_name'].geohashDistanceInKm(geohash)` |The `arc` distance (in km)
  212. of this geo point field from the provided geohash.
  213. |`doc['field_name'].geohashDistanceInMiles(geohash)` |The `arc` distance (in
  214. miles) of this geo point field from the provided geohash.
  215. |=======================================================================
  216. [float]
  217. === Stored Fields
  218. Stored fields can also be accessed when executing a script. Note, they
  219. are much slower to access compared with document fields, as they are not
  220. loaded into memory. They can be simply accessed using
  221. `_fields['my_field_name'].value` or `_fields['my_field_name'].values`.
  222. [float]
  223. === Source Field
  224. The source field can also be accessed when executing a script. The
  225. source field is loaded per doc, parsed, and then provided to the script
  226. for evaluation. The `_source` forms the context under which the source
  227. field can be accessed, for example `_source.obj2.obj1.field3`.
  228. Accessing `_source` is much slower compared to using `_doc`
  229. but the data is not loaded into memory. For a single field access `_fields` may be
  230. faster than using `_source` due to the extra overhead of potentially parsing large documents.
  231. However, `_source` may be faster if you access multiple fields or if the source has already been
  232. loaded for other purposes.
  233. [float]
  234. === Groovy Built In Functions
  235. There are several built in functions that can be used within scripts.
  236. They include:
  237. [cols="<,<",options="header",]
  238. |=======================================================================
  239. |Function |Description
  240. |`sin(a)` |Returns the trigonometric sine of an angle.
  241. |`cos(a)` |Returns the trigonometric cosine of an angle.
  242. |`tan(a)` |Returns the trigonometric tangent of an angle.
  243. |`asin(a)` |Returns the arc sine of a value.
  244. |`acos(a)` |Returns the arc cosine of a value.
  245. |`atan(a)` |Returns the arc tangent of a value.
  246. |`toRadians(angdeg)` |Converts an angle measured in degrees to an
  247. approximately equivalent angle measured in radians
  248. |`toDegrees(angrad)` |Converts an angle measured in radians to an
  249. approximately equivalent angle measured in degrees.
  250. |`exp(a)` |Returns Euler's number _e_ raised to the power of value.
  251. |`log(a)` |Returns the natural logarithm (base _e_) of a value.
  252. |`log10(a)` |Returns the base 10 logarithm of a value.
  253. |`sqrt(a)` |Returns the correctly rounded positive square root of a
  254. value.
  255. |`cbrt(a)` |Returns the cube root of a double value.
  256. |`IEEEremainder(f1, f2)` |Computes the remainder operation on two
  257. arguments as prescribed by the IEEE 754 standard.
  258. |`ceil(a)` |Returns the smallest (closest to negative infinity) value
  259. that is greater than or equal to the argument and is equal to a
  260. mathematical integer.
  261. |`floor(a)` |Returns the largest (closest to positive infinity) value
  262. that is less than or equal to the argument and is equal to a
  263. mathematical integer.
  264. |`rint(a)` |Returns the value that is closest in value to the argument
  265. and is equal to a mathematical integer.
  266. |`atan2(y, x)` |Returns the angle _theta_ from the conversion of
  267. rectangular coordinates (_x_, _y_) to polar coordinates (r,_theta_).
  268. |`pow(a, b)` |Returns the value of the first argument raised to the
  269. power of the second argument.
  270. |`round(a)` |Returns the closest _int_ to the argument.
  271. |`random()` |Returns a random _double_ value.
  272. |`abs(a)` |Returns the absolute value of a value.
  273. |`max(a, b)` |Returns the greater of two values.
  274. |`min(a, b)` |Returns the smaller of two values.
  275. |`ulp(d)` |Returns the size of an ulp of the argument.
  276. |`signum(d)` |Returns the signum function of the argument.
  277. |`sinh(x)` |Returns the hyperbolic sine of a value.
  278. |`cosh(x)` |Returns the hyperbolic cosine of a value.
  279. |`tanh(x)` |Returns the hyperbolic tangent of a value.
  280. |`hypot(x, y)` |Returns sqrt(_x2_ + _y2_) without intermediate overflow
  281. or underflow.
  282. |=======================================================================
  283. [float]
  284. === Arithmetic precision in MVEL
  285. When dividing two numbers using MVEL based scripts, the engine tries to
  286. be smart and adheres to the default behaviour of java. This means if you
  287. divide two integers (you might have configured the fields as integer in
  288. the mapping), the result will also be an integer. This means, if a
  289. calculation like `1/num` is happening in your scripts and `num` is an
  290. integer with the value of `8`, the result is `0` even though you were
  291. expecting it to be `0.125`. You may need to enforce precision by
  292. explicitly using a double like `1.0/num` in order to get the expected
  293. result.