Skip to content

Instantly share code, notes, and snippets.

@hkorte
Last active September 14, 2018 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hkorte/cb20352171702446505d6bee693114a3 to your computer and use it in GitHub Desktop.
Save hkorte/cb20352171702446505d6bee693114a3 to your computer and use it in GitHub Desktop.
This example shows a strange behavior of the Elasticsearch TransportClient in version 5.6.11
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>toyexample</groupId>
<artifactId>es-tester</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.11</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.11</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>5.6.11</version>
</dependency>
</dependencies>
</project>
package test;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.testcontainers.containers.GenericContainer;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Collections;
import java.util.Map;
public class PutStoredScriptExample {
public static void main(String[] args) throws IOException {
// start an ES node, a transport client, and a rest client
GenericContainer service =
new GenericContainer("docker.elastic.co/elasticsearch/elasticsearch:5.6.11")
.withEnv("xpack.security.enabled", "false")
.withExposedPorts(9200, 9300);
service.start();
String ip = service.getContainerIpAddress();
RestClient restClient =
RestClient.builder(new HttpHost(ip, service.getMappedPort(9200), "http")).build();
Settings settings = Settings.builder().put("cluster.name", "docker-cluster").build();
TransportClient transportClient =
new PreBuiltTransportClient(settings)
.addTransportAddress(
new InetSocketTransportAddress(
InetAddress.getByName(ip), service.getMappedPort(9300)));
// store a script using the transport client
String scriptSource = "{\"size\": 6,\"query\": {\"match_all\": {}}}";
transportClient
.admin()
.cluster()
.preparePutStoredScript()
.setId("TEST1")
.setLang("mustache")
.setContent(new BytesArray(scriptSource), XContentType.JSON)
.get();
// actually stored is only the first field of the source!
// this prints:
// {"_id":"TEST1","found":true,"script":{"lang":"mustache","source":"{\"size\":6}"}}
Response response = restClient.performRequest("GET", "/_scripts/TEST1");
System.out.println(EntityUtils.toString(response.getEntity()));
// we swap the field order in the source..
scriptSource = "{\"query\": {\"match_all\": {}},\"size\": 6}";
transportClient
.admin()
.cluster()
.preparePutStoredScript()
.setId("TEST2")
.setLang("mustache")
.setContent(new BytesArray(scriptSource), XContentType.JSON)
.get();
// now only the query is stored - the size field is ignored!
// this prints:
// {"_id":"TEST2","found":true,"script":{"lang":"mustache","source":"{\"query\":{\"match_all\":{}}}"}}
response = restClient.performRequest("GET", "/_scripts/TEST2");
System.out.println(EntityUtils.toString(response.getEntity()));
// we try to store the same script using the rest client
Map<String, String> params = Collections.emptyMap();
String body = "{\"script\":{\"lang\":\"mustache\",\"source\":" + scriptSource + "}}";
HttpEntity entity = new NStringEntity(body, ContentType.APPLICATION_JSON);
restClient.performRequest("PUT", "/_scripts/TEST3", params, entity);
// using the rest client the whole script with query and size fields is stored..
// this prints:
// {"_id":"TEST3","found":true,"script":{"lang":"mustache","source":"{\"query\":{\"match_all\":{}},\"size\":6}","options":{"content_type":"application/json; charset=UTF-8"}}}
response = restClient.performRequest("GET", "/_scripts/TEST3");
System.out.println(EntityUtils.toString(response.getEntity()));
// as it turned out, the trick is to wrap the script source in a script element..
// see: https://discuss.elastic.co/t/scripts-stored-via-transportclient-lose-fields-in-source/148473/3
transportClient
.admin()
.cluster()
.preparePutStoredScript()
.setId("TEST4")
.setLang("mustache")
.setContent(new BytesArray("{\"script\":" + scriptSource + "}"), XContentType.JSON)
.get();
// and - tadaa - the whole script with query and size fields is stored!
// this prints:
// {"_id":"TEST4","found":true,"script":{"lang":"mustache","source":"{\"query\":{\"match_all\":{}},\"size\":6}"}}
response = restClient.performRequest("GET", "/_scripts/TEST4");
System.out.println(EntityUtils.toString(response.getEntity()));
transportClient.close();
restClient.close();
service.stop();
service.close();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment