This plugin contains several examples of native script for Elasticsearch.
The simplest way to deploy native script is by wrapping it into standard Elasticsearch plugin infrastructure. An Elasticsearch plugin can be written in java and built using maven. A typical plugin source directory looks like this:
.
|- pom.xml
|- src
|- main
|- assemblies
| |- plugin.xml
|- java
| |- ... source code ...
|- resources
|- es-plugin.properties
An Elasticsearch plugin can be created by following these six steps.
- Create pom.xml file in the root directory of your plugin. The pom.xml file in this project can be used as a starting point.
- Create source code directories:
mkdir -p src/main/assemblies
mkdir -p src/main/java
mkdir -p src/main/resources
- Download plugin.xml to the
src/main/assemblies
directory. This file specifies how plugin .zip package should be built. By default, the project artifact with all its dependencies is going to be included in the plugin package. For more information on how to configure the content of the package, see Maven Assembly Plugin Documentation. - Create main Plugin class in the
src/main/java
directory. This project is usingorg.elasticsearch.examples.nativescript.plugin.NativeScriptExamplesPlugin
class as an example, so the it has to be saved assrc/main/java/org/elasticsearch/examples/nativescript/plugin/NativeScriptExamplesPlugin.java
package org.elasticsearch.examples.nativescript.plugin;
import org.elasticsearch.examples.nativescript.script.DividedBoostScoreSearchScript; import org.elasticsearch.plugins.AbstractPlugin; import org.elasticsearch.script.ScriptModule;
public class NativeScriptExamplesPlugin extends AbstractPlugin { @Override public String name() { return "native-script-examples"; }
@Override public String description() { return "Examples of native script"; } }
- Create
es-plugin.properties
file in thesrc/main/resources
directory to point to the Plugin class that was created in the previous step:
plugin=org.elasticsearch.examples.nativescript.plugin.NativeScriptExamplesPlugin
- The plugin can be built using
mvn package
command. The assembled .zip package can be found in thetarget/releases/
directory and deployed to elasticsearch installation usingplugin -install plugin-name -url path/to/plugin/zip/file
.
Now that the plugin infrastructure is complete, it’s possible to add a native script.
One of the example scripts in this project is the “is_prime” script that can be used to check if a field contains a possible prime number. The script accepts two parameters field
and certainty
. The field
parameter contains the name of the field that needs to be checked and the certainty
parameter specifies a measure of the uncertainty that the caller is willing to tolerate. The script returns true
if the field contains a probable prime number and false
otherwise. The probability that the number for which the script returned true
is prime exceeds (1 – 0.5^certainty). The script can be used in Script Filter as well as a Script Field. The implementation of the “is_prime” native script and it’s factory can be found in the IsPrimeSearchScript class.
In order to enable native script creation the plugin has to contain and register a class that implements NativeScriptFactory. The NativeScriptFactory interface has only one method newScript(Map<String, Object> params)
. This method accepts a list of parameters that are passed during script creation and returns an ExecutableScript object with an instance of the script. The factory has to be registered in the onModule(ScriptModule module)
method of the Plugin.
public class NativeScriptExamplesPlugin extends AbstractPlugin {
/* ..... */
public void onModule(ScriptModule module) {
// Register each script that we defined in this plugin
module.registerScript("is_prime", IsPrimeSearchScript.Factory.class);
}
}
In general native scripts have to implement the interface ExecutableScript, but if they are used in search, they have to also implement the SearchScript interface. The SearchScript interface is quite complex, so in order to simplify implementation, the native script can simply extend the AbstractSearchScript class instead. The AbstractSearchScript has only one abstract method run()
. During search Elasticsearch calls this method for every single record in the search result. As in case of non-native script, the content of the current record can be accessed using DocLookup (doc()
method), FieldsLookup (fields()
method), SourceLookup (source()
method).
The lookup script demonstrates how to make elsticsearch client available within the native script. When script factory is initially created, the node is not fully initialized yet. Because of this client cannot be directory injected into the factory. Instead, the reference to the node is injected and the client is obtained from the node during script creation. A same mechanism can be used to obtain other node components through node injector.
The random sort script demonstrates a slightly different approach to script/factory packaging. In this case the factory is the outer class which creates one inner script or another based on the input parameters. If the parameter salt
is present, the script is calculating hash value of id + salt
instead of generation random sort values. As a result, for any value of salt
the order of the records will appear random, but this order will be repeatable and therefore this approach would be more suitable for paging through result list than a completely random approach.