= Elasticsearch Rest Component
:doctitle: Elasticsearch Rest
:shortname: elasticsearch-rest
:artifactid: camel-elasticsearch-rest
:description: Send requests to ElasticSearch via REST API
:since: 2.21
:supportlevel: Stable
:component-header: Only producer is supported
//Manually maintained attributes
:camel-spring-boot-name: elasticsearch-rest

*Since Camel {since}*

*{component-header}*

The ElasticSearch component allows you to interface with an
https://www.elastic.co/products/elasticsearch[ElasticSearch] 6.x API using the REST Client library.

Maven users will need to add the following dependency to their `pom.xml`
for this component:

[source,xml]
----
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-elasticsearch-rest</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>
----

== URI format

----
elasticsearch-rest://clusterName[?options]
----


// component-configure options: START

// component-configure options: END

// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
// component options: END

// endpoint options: START

// endpoint options: END



== Message Operations

The following ElasticSearch operations are currently supported. Simply
set an endpoint URI option or exchange header with a key of "operation"
and a value set to one of the following. Some operations also require
other parameters or the message body to be set.

[width="100%",cols="10%,10%,80%",options="header",]
|===
|operation |message body |description

|Index |*Map*, *String*, *byte[]*, *XContentBuilder* or *IndexRequest* content to index |Adds content to an index and returns the content's indexId in the body.
You can set the indexId by setting the message header with
the key "indexId".

|GetById |*String* or *GetRequest* index id of content to retrieve |Retrieves the specified index and returns a GetResult object in the body

|Delete |*String* or *DeleteRequest* index name and type of content to delete |Deletes the specified indexName and indexType and returns a DeleteResponse object in the
body

|DeleteIndex |*String* or *DeleteRequest* index name of the index to delete |Deletes the specified indexName and returns a status code the
body

|BulkIndex | a *List*, *BulkRequest*, or *Collection* of any type that is already accepted
(XContentBuilder, Map, byte[], String) |Adds content to an index and return a List of the id of the
successfully indexed documents in the body

|Bulk |a *List*, *BulkRequest*, or *Collection* of any type that is already accepted
       (XContentBuilder, Map, byte[], String) |Adds content to an index and returns the BulkItemResponse[]
object in the body

|Search |*Map*, *String* or *SearchRequest* |Search the content with the map of query string

|MultiSearch |*MultiSearchRequest* |Multiple search in one

|Exists |Index name(indexName) as header  |Checks the index exists or not and returns a Boolean flag in the body

|Update |*Map*, *UpdateRequest*, *String*, *byte[]* or *XContentBuilder* content to update |Updates content to an index and returns the content's
indexId in the body.

|Ping |None  |Pings the remote Elasticsearch cluster and returns true if the ping succeeded, false otherwise

|===

== Configure the component and enable basic authentication
To use the Elasticsearch component it has to be configured with a minimum configuration.

[source,java]
----
ElasticsearchComponent elasticsearchComponent = new ElasticsearchComponent();
elasticsearchComponent.setHostAddresses("myelkhost:9200");
camelContext.addComponent("elasticsearch-rest", elasticsearchComponent);
----

For basic authentication with elasticsearch or using reverse http proxy in front of the elasticsearch cluster, simply setup
basic authentication and SSL on the component like the example below

[source,java]
----
ElasticsearchComponent elasticsearchComponent = new ElasticsearchComponent();
elasticsearchComponent.setHostAddresses("myelkhost:9200");
elasticsearchComponent.setUser("elkuser");
elasticsearchComponent.setPassword("secure!!");
elasticsearchComponent.setEnableSSL(true);

camelContext.addComponent("elasticsearch-rest", elasticsearchComponent);
----

== Index Example

Below is a simple INDEX example

[source,java]
----
from("direct:index")
  .to("elasticsearch-rest://elasticsearch?operation=Index&indexName=twitter");
----

[source,xml]
----
<route>
    <from uri="direct:index"/>
    <to uri="elasticsearch-rest://elasticsearch?operation=Index&amp;indexName=twitter"/>
</route>
----

*For this operation you'll need to specify a indexId header.*

A client would simply need to pass a body message containing a Map to
the route. The result body contains the indexId created.

[source,java]
----
Map<String, String> map = new HashMap<String, String>();
map.put("content", "test");
String indexId = template.requestBody("direct:index", map, String.class);
----

== Search Example

Searching on specific field(s) and value use the Operation ´Search´.
Pass in the query JSON String or the Map

[source,java]
----
from("direct:search")
  .to("elasticsearch-rest://elasticsearch?operation=Search&indexName=twitter");
----

[source,xml]
----
<route>
    <from uri="direct:search"/>
    <to uri="elasticsearch-rest://elasticsearch?operation=Search&amp;indexName=twitter"/>
</route>
----

[source,java]
----
String query = "{\"query\":{\"match\":{\"content\":\"new release of ApacheCamel\"}}}";
SearchHits response = template.requestBody("direct:search", query, SearchHits.class);

----

Search on specific field(s) using Map.

[source,java]
----
Map<String, Object> actualQuery = new HashMap<>();
actualQuery.put("content", "new release of ApacheCamel");

Map<String, Object> match = new HashMap<>();
match.put("match", actualQuery);

Map<String, Object> query = new HashMap<>();
query.put("query", match);
SearchHits response = template.requestBody("direct:search", query, SearchHits.class);

----

Search using Elasticsearch scroll api in order to fetch all results.

[source,java]
----
from("direct:search")
  .to("elasticsearch-rest://elasticsearch?operation=Search&indexName=twitter&useScroll=true&scrollKeepAliveMs=30000");
----

[source,xml]
----
<route>
    <from uri="direct:search"/>
    <to uri="elasticsearch-rest://elasticsearch?operation=Search&amp;indexName=twitter&amp;useScroll=true&amp;scrollKeepAliveMs=30000"/>
</route>
----

[source,java]
----
String query = "{\"query\":{\"match\":{\"content\":\"new release of ApacheCamel\"}}}";
try (ElasticsearchScrollRequestIterator response = template.requestBody("direct:search", query, ElasticsearchScrollRequestIterator.class)) {
    // do something smart with results
}
----

xref:eips:split-eip.adoc[Split EIP] can also be used.

[source,java]
----
from("direct:search")
  .to("elasticsearch-rest://elasticsearch?operation=Search&indexName=twitter&useScroll=true&scrollKeepAliveMs=30000")
  .split()
  .body()
  .streaming()
  .to("mock:output")
  .end();
----

== MultiSearch Example

MultiSearching on specific field(s) and value use the Operation ´MultiSearch´.
Pass in the MultiSearchRequest instance

[source,java]
----
from("direct:multiSearch")
  .to("elasticsearch-rest://elasticsearch?operation=MultiSearch");
----

[source,xml]
----
<route>
    <from uri="direct:multiSearch"/>
    <to uri="elasticsearch-rest://elasticsearch?operation=MultiSearch"/>
</route>
----

MultiSearch on specific field(s) 

[source,java]
----
SearchRequest req = new SearchRequest();
req.indices("twitter");
SearchRequest req1 = new SearchRequest();
req.indices("twitter");
MultiSearchRequest request = new MultiSearchRequest().add(req1).add(req);
Item[] response = template.requestBody("direct:search", request, Item[].class);
----


include::spring-boot:partial$starter.adoc[]
