Browse Source

Tidied the Painless docs and added the experimental tag

Clinton Gormley 9 years ago
parent
commit
08903f1ed8
1 changed files with 167 additions and 132 deletions
  1. 167 132
      docs/reference/modules/painless.asciidoc

+ 167 - 132
docs/reference/modules/painless.asciidoc

@@ -1,19 +1,21 @@
 [[modules-scripting-painless]]
 == Painless Scripting Language
 
-_Painless_ is a simple, secure scripting language built in to Elasticsearch as a module. 
+experimental[The Painless scripting language is new and is still marked as experimental. The syntax or API may be changed in the future in non-backwards compatible ways if required.]
+
+_Painless_ is a simple, secure scripting language built in to Elasticsearch as a module.
 It is designed specifically for use with Elasticsearch and can safely be used dynamically.
 
-A Painless script is essentially a single function. Painless does not provide support 
-for defining multiple functions within a script. The Painless syntax is similar to 
-http://groovy-lang.org/index.html[Groovy]. 
+A Painless script is essentially a single function. Painless does not provide support
+for defining multiple functions within a script. The Painless syntax is similar to
+http://groovy-lang.org/index.html[Groovy].
 
-You can use Painless anywhere a script can be used in Elasticsearch--simply set the `lang` parameter 
+You can use Painless anywhere a script can be used in Elasticsearch--simply set the `lang` parameter
 to `painless`.
 
 [[painless-features]]
 [float]
-=== Painless Features
+== Painless Features
 
 * Control flow: `for` loops, `while` loops, `do/while` loops, `if/else`
 
@@ -32,196 +34,229 @@ to `painless`.
 
 [[painless-examples]]
 [float]
-=== Painless Examples
+== Painless Examples
 
 To illustrate how Painless works, let's load some hockey stats into an Elasticsearch index:
 
 [source,sh]
 ----------------------------------------------------------------
-curl -XDELETE http://localhost:9200/hockey-stats
-curl -XPUT http://localhost:9200/hockey-stats
-curl -XPUT http://localhost:9200/hockey-stats/player/1 -d '{"first":"johnny", "last":"gaudreau", "goals":[9, 27, 1], "assists":[17, 46, 0], "gp":[26, 82, 1]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/2 -d '{"first":"sean", "last":"monohan", "goals":[7, 54, 26], "assists":[11, 26, 13], "gp":[26, 82, 82]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/3 -d '{"first":"jiri", "last":"hudler", "goals":[5, 34, 36], "assists":[11, 62, 42], "gp":[24, 80, 79]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/4 -d '{"first":"micheal", "last":"frolik", "goals":[4, 6, 15], "assists":[8, 23, 15], "gp":[26, 82, 82]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/5 -d '{"first":"sam", "last":"bennett", "goals":[5, 0, 0], "assists":[8, 1, 0], "gp":[26, 1, 0]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/6 -d '{"first":"dennis", "last":"wideman", "goals":[0, 26, 15], "assists":[11, 30, 24], "gp":[26, 81, 82]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/7 -d '{"first":"david", "last":"jones", "goals":[7, 19, 5], "assists":[3, 17, 4], "gp":[26, 45, 34]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/8 -d '{"first":"tj", "last":"brodie", "goals":[2, 14, 7], "assists":[8, 42, 30], "gp":[26, 82, 82]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/9 -d '{"first":"mark", "last":"giordano", "goals":[6, 30, 15], "assists":[3, 30, 24], "gp":[26, 60, 63]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/10 -d '{"first":"mikael", "last":"backlund", "goals":[3, 15, 13], "assists":[6, 24, 18], "gp":[26, 82, 82]}'
-curl -XPUT http://localhost:9200/hockey-stats/player/11 -d '{"first":"joe", "last":"colborne", "goals":[3, 18, 13], "assists":[6, 20, 24], "gp":[26, 67, 82]}'
+DELETE /hockey-stats
+
+PUT /hockey-stats/player/_bulk
+{"index":{"_id":1}}
+{"first":"johnny","last":"gaudreau","goals":[9,27,1],"assists":[17,46,0],"gp":[26,82,1]}
+{"index":{"_id":2}}
+{"first":"sean","last":"monohan","goals":[7,54,26],"assists":[11,26,13],"gp":[26,82,82]}
+{"index":{"_id":3}}
+{"first":"jiri","last":"hudler","goals":[5,34,36],"assists":[11,62,42],"gp":[24,80,79]}
+{"index":{"_id":4}}
+{"first":"micheal","last":"frolik","goals":[4,6,15],"assists":[8,23,15],"gp":[26,82,82]}
+{"index":{"_id":5}}
+{"first":"sam","last":"bennett","goals":[5,0,0],"assists":[8,1,0],"gp":[26,1,0]}
+{"index":{"_id":6}}
+{"first":"dennis","last":"wideman","goals":[0,26,15],"assists":[11,30,24],"gp":[26,81,82]}
+{"index":{"_id":7}}
+{"first":"david","last":"jones","goals":[7,19,5],"assists":[3,17,4],"gp":[26,45,34]}
+{"index":{"_id":8}}
+{"first":"tj","last":"brodie","goals":[2,14,7],"assists":[8,42,30],"gp":[26,82,82]}
+{"index":{"_id":39}}
+{"first":"mark","last":"giordano","goals":[6,30,15],"assists":[3,30,24],"gp":[26,60,63]}
+{"index":{"_id":10}}
+{"first":"mikael","last":"backlund","goals":[3,15,13],"assists":[6,24,18],"gp":[26,82,82]}
+{"index":{"_id":11}}
+{"first":"joe","last":"colborne","goals":[3,18,13],"assists":[6,20,24],"gp":[26,67,82]}
 ----------------------------------------------------------------
+// AUTOSENSE
 
 [float]
-==== Accessing Doc Values from Painless
+=== Accessing Doc Values from Painless
 
-All Painless scripts take in a `Map<String,def>` of values called `input`.  Document values can be accessed through another `Map<String,def>` within the `input` variable.  
+All Painless scripts take in a `Map<String,def>` of values called `input`.  Document values can be accessed through another `Map<String,def>` within the `input` variable.
 
-For example, the following script calculates a player's total goals. This example uses a strongly typed `int` and a `for` loop.  
+For example, the following script calculates a player's total goals. This example uses a strongly typed `int` and a `for` loop.
 
 [source,sh]
 ----------------------------------------------------------------
-curl -XGET http://localhost:9200/hockey-stats/_search -d '{
-   "query": {
-      "function_score": {
-         "script_score" : {
-            "script" : {
-               "inline": 
-                  "int total = 0; for (int i = 0; i < input.doc.goals.size(); ++i) { total += input.doc.goals[i]; } return total;", 
-               "lang": "painless"
-            }
+GET /hockey-stats/_search
+{
+  "query": {
+    "function_score": {
+      "script_score": {
+        "script": {
+          "lang": "painless",
+          "inline": "int total = 0; for (int i = 0; i < input.doc.goals.size(); ++i) { total += input.doc.goals[i]; } return total;"
         }
+      }
     }
-   }
-}'
+  }
+}
 ----------------------------------------------------------------
+// AUTOSENSE
 
 Alternatively, you could do the same thing using a script field instead of a function score:
 
 [source,sh]
 ----------------------------------------------------------------
-curl -XGET http://localhost:9200/hockey-stats/_search -d '{
-   "query": {
-      "match_all": {}}, 
-      "script_fields": {
-         "total_goals": {
-            "script": {
-               "inline": "int total = 0; for (int i = 0; i < input.doc.goals.size(); ++i) { total += input.doc.goals[i]; } return total;", 
-               "lang": "painless"
-            }
-        }
+GET /hockey-stats/_search
+{
+  "query": {
+    "match_all": {}
+  },
+  "script_fields": {
+    "total_goals": {
+      "script": {
+        "lang": "painless",
+        "inline": "int total = 0; for (int i = 0; i < input.doc.goals.size(); ++i) { total += input.doc.goals[i]; } return total;"
+      }
     }
-}'
+  }
+}
 ----------------------------------------------------------------
+// AUTOSENSE
 
-You must always specify the index of the field value you want, even if there's only a single item in the field. 
+You must always specify the index of the field value you want, even if there's only a single item in the field.
 All fields in Elasticsearch are multi-valued and Painless does not provide a `.value` shortcut. The following example uses a Painless script to sort the players by their combined first and last names. The names are accessed using
-`input.doc.first.0` and `input.doc.last.0`.  
+`input.doc.first.0` and `input.doc.last.0`.
 
 [source,sh]
 ----------------------------------------------------------------
-curl -XGET http://localhost:9200/hockey-stats/_search -d '{
-   "query" : {
-      "match_all": {}}, 
-      "sort" : {
-         "_script" : {
-            "type" : "string", 
-            "script" : {"inline": "input.doc.first.0 + \" \" + input.doc.last.0", 
-            "lang": "painless"}, 
-            "order" : "asc"
-        }
+GET /hockey-stats/_search
+{
+  "query": {
+    "match_all": {}
+  },
+  "sort": {
+    "_script": {
+      "type": "string",
+      "order": "asc",
+      "script": {
+        "lang": "painless",
+        "inline": "input.doc.first.0 + \" \" + input.doc.last.0"
+      }
     }
-}'
+  }
+}
 ----------------------------------------------------------------
+// AUTOSENSE
 
 [float]
-==== Updating Fields with Painless 
+=== Updating Fields with Painless
 
-You can also easily update fields. You access the original source for a field as `input.ctx._source.<field-name>`. 
+You can also easily update fields. You access the original source for a field as `input.ctx._source.<field-name>`.
 
 First, let's look at the source data for a player by submitting the following request:
 
 [source,sh]
 ----------------------------------------------------------------
-curl -XGET http://localhost:9200/hockey-stats/_search -d '{
-   "fields" : ["_id", "_source"], "query" : {
-      "term" : { "_id" : 1 }
+GET /hockey-stats/_search
+{
+  "fields": [
+    "_id",
+    "_source"
+  ],
+  "query": {
+    "term": {
+      "_id": 1
     }
-}'
+  }
+}
 ----------------------------------------------------------------
+// AUTOSENSE
 
-To change player 1's last name to _hockey_, simply set `input.ctx._source.last` to the new value:
+To change player 1's last name to `hockey`, simply set `input.ctx._source.last` to the new value:
 
 [source,sh]
 ----------------------------------------------------------------
-curl -XPOST http://localhost:9200/hockey-stats/player/1/_update -d '{
-   "script": {
-      "inline": "input.ctx._source.last = input.last", 
-      "params": {"last": "hockey"}, 
-      "lang": "painless"
-   }
-}'
+POST /hockey-stats/player/1/_update
+{
+  "script": {
+    "lang": "painless",
+    "inline": "input.ctx._source.last = input.last",
+    "params": {
+      "last": "hockey"
+    }
+  }
+}
 ----------------------------------------------------------------
+// AUTOSENSE
 
-You can also add fields to a document. For example, this script adds a new field that contains 
+You can also add fields to a document. For example, this script adds a new field that contains
 the player's nickname,  _hockey_.
 
 [source,sh]
 ----------------------------------------------------------------
-curl -XPOST http://localhost:9200/hockey-stats/player/1/_update -d '{
-   "script": {
-      "inline": "input.ctx._source.last = input.last input.ctx._source.nick = input.nick", 
-      "params": {"last": "gaudreau", "nick": "hockey"}, 
-      "lang": "painless"
-   }
-}'
+POST /hockey-stats/player/1/_update
+{
+  "script": {
+    "lang": "painless",
+    "inline": "input.ctx._source.last = input.last input.ctx._source.nick = input.nick",
+    "params": {
+      "last": "gaudreau",
+      "nick": "hockey"
+    }
+  }
+}
 ----------------------------------------------------------------
+// AUTOSENSE
 
 [float]
-==== Writing Type-Safe Scripts to Improve Performance
+=== Writing Type-Safe Scripts to Improve Performance
 
-If you explicitly specify types, the compiler doesn't have to perform type lookups at runtime, which can significantly 
-improve performance. For example, the following script performs the same first name, last name sort we showed before, 
+If you explicitly specify types, the compiler doesn't have to perform type lookups at runtime, which can significantly
+improve performance. For example, the following script performs the same first name, last name sort we showed before,
 but it's fully type-safe.
 
 [source,sh]
 ----------------------------------------------------------------
-curl -XGET http://localhost:9200/hockey-stats/_search -d '{
-   "query": {
-      "match_all": {}
-   }, 
-   "script_fields": {
-      "full_name_dynamic": {
-         "script": {
-            "inline": "def first = input.doc.first.0; def last = input.doc.last.0; return first + \" \" + last;", 
-            "lang": "painless"
-         }
-      }, 
-      "full_name_static": {
-         "script": {
-            "inline": 
-               "String first = (String)((List)((Map)input.get(\"doc\")).get(\"first\")).get(0); String last = (String)((List)((Map)input.get(\"doc\")).get(\"last\")).get(0); return first + \" \" + last;", 
-           "lang": "painless"
-         }
-       }
+GET /hockey-stats/_search
+{
+  "query": {
+    "match_all": {}
+  },
+  "script_fields": {
+    "full_name_dynamic": {
+      "script": {
+        "lang": "painless",
+        "inline": "def first = input.doc.first.0; def last = input.doc.last.0; return first + \" \" + last;"
+      }
+    },
+    "full_name_static": {
+      "script": {
+        "lang": "painless",
+        "inline": "String first = (String)((List)((Map)input.get(\"doc\")).get(\"first\")).get(0); String last = (String)((List)((Map)input.get(\"doc\")).get(\"last\")).get(0); return first + \" \" + last;"
+      }
     }
-}'
+  }
+}
 ----------------------------------------------------------------
+// AUTOSENSE
 
 [[painless-api]]
 [float]
-=== Painless API
+== Painless API
 
 The following types are available for use in the Painless language. Most types and methods map directly to their Java equivalents--for more information, see the corresponding https://docs.oracle.com/javase/8/docs/api/java/lang/package-summary.html[Javadoc].
 
 
 [float]
-==== Dynamic Types
+=== Dynamic Types
 
-`def` (This type can be used to represent any other type.)
+* `def` (This type can be used to represent any other type.)
 
 [float]
-==== Basic Types
-
-`void`
-
-`boolean`
-
-`short`
-
-`char`
+=== Basic Types
 
-`int`
-
-`long`
-
-`float`
-
-`double`
+* `void`
+* `boolean`
+* `short`
+* `char`
+* `int`
+* `long`
+* `float`
+* `double`
 
 [float]
-==== Complex Types
+=== Complex Types
 
 Non-static methods/members in superclasses are available to subclasses.
 Generic types with unspecified generic parameters are parameters of type `def`.
@@ -242,7 +277,7 @@ ArrayList<Object> extends List<Object>
 -----
 
 -----
-ArrayList<String> extends List<String>    
+ArrayList<String> extends List<String>
     <init>()
 -----
 
@@ -254,13 +289,13 @@ Boolean extends Object
 -----
 
 -----
-Character extends Object    
+Character extends Object
     <init>(char)
     static Character valueOf(char)
     char charValue()
     static char MIN_VALUE
     static char MAX_VALUE
------    
+-----
 
 -----
 CharSequence extends Object
@@ -311,7 +346,7 @@ Double extends Number
 
 -----
 Exception extends Object
-    String getMessage()    
+    String getMessage()
 -----
 
 -----
@@ -324,7 +359,7 @@ Float extends Number
 
 -----
 HashMap extends Map
-    <init>()    
+    <init>()
 -----
 
 -----
@@ -334,14 +369,14 @@ HashMap<Object,Object> extends Map<Object,Object>
 
 -----
 HashMap<String,def> extends Map<String,def>
-    <init>()    
+    <init>()
 -----
 
 -----
 HashMap<String,Object> extends Map<String,Object>
     <init>()
 -----
-    
+
 -----
 IllegalArgument extends Exception
     <init>()
@@ -349,7 +384,7 @@ IllegalArgument extends Exception
 
 -----
 IllegalState extends Exception
-    <init>()    
+    <init>()
 -----
 
 -----
@@ -413,7 +448,7 @@ Map extends Object
     boolean containsKey(def)
     boolean containsValue(def)
     Set keySet()
-    Collection values()    
+    Collection values()
 -----
 
 -----
@@ -549,7 +584,7 @@ Math
    static double min(double, double)
    static float fmin(float, float)
    static long lmin(long, long)
-   static int imin(int, int)   
+   static int imin(int, int)
    static double pow(double, double)
    static double random()
    static double rint(double)