This is an automated email from the ASF dual-hosted git repository.

nfilotto pushed a commit to branch CAMEL-19752/add-document-only-mode-3.20
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f9f076b515c5561e394be71f7036dc98d45085fa
Author: Nicolas Filotto <nfilo...@talend.com>
AuthorDate: Fri Sep 1 16:13:14 2023 +0200

    CAMEL-19752: camel-elasticsearch - Add a doc-only mode to ease migration
---
 .../camel/catalog/components/elasticsearch.json    |   5 +-
 .../es/ElasticsearchComponentConfigurer.java       |   6 +
 .../es/ElasticsearchEndpointConfigurer.java        |   6 +
 .../es/ElasticsearchEndpointUriFactory.java        |   3 +-
 .../apache/camel/component/es/elasticsearch.json   |   5 +-
 .../src/main/docs/elasticsearch-component.adoc     |  12 +-
 .../camel/component/es/ElasticsearchComponent.java |  18 +++
 .../component/es/ElasticsearchConfiguration.java   |  17 +++
 .../camel/component/es/ElasticsearchConstants.java |   2 +
 .../camel/component/es/ElasticsearchProducer.java  |   5 +
 .../ElasticsearchActionRequestConverter.java       |  41 +++++-
 .../es/integration/ElasticsearchBulkIT.java        |   7 +-
 ...ElasticsearchGetSearchDeleteExistsUpdateIT.java | 161 ++++++++++++++++++---
 .../dsl/ElasticsearchComponentBuilderFactory.java  |  20 +++
 .../dsl/ElasticsearchEndpointBuilderFactory.java   |  53 +++++++
 15 files changed, 327 insertions(+), 34 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/elasticsearch.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/elasticsearch.json
index c3bdd2e6188..81a02fe7d28 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/elasticsearch.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/elasticsearch.json
@@ -23,6 +23,7 @@
   },
   "componentProperties": {
     "connectionTimeout": { "kind": "property", "displayName": "Connection 
Timeout", "group": "producer", "label": "", "required": false, "type": 
"integer", "javaType": "int", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "description": "The time in ms to wait 
before connection will timeout." },
+    "enableDocumentOnlyMode": { "kind": "property", "displayName": "Enable 
Document Only Mode", "group": "producer", "label": "", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": false, "description": "Indicates 
whether the body of the message contains only documents. By default, it is set 
to false to be able to do the same requests as what the Document API supports 
(see https:\/\/www.elastic.co\/guide\ [...]
     "hostAddresses": { "kind": "property", "displayName": "Host Addresses", 
"group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "Comma separated list with ip:port formatted 
remote transport addresses to use. The ip and port options must be left blank 
for hostAddresses to be considered instead." },
     "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start 
Producer", "group": "producer", "label": "producer", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "Whether the producer 
should be started lazy (on the first message). By starting lazy you can use 
this to allow CamelContext and routes to startup in situations where a producer 
may otherwise fail during star [...]
     "maxRetryTimeout": { "kind": "property", "displayName": "Max Retry 
Timeout", "group": "producer", "label": "", "required": false, "type": 
"integer", "javaType": "int", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "description": "The time in ms before 
retry" },
@@ -46,12 +47,14 @@
     "scrollKeepAliveMs": { "kind": "header", "displayName": "", "group": 
"producer", "label": "", "required": false, "javaType": "Integer", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The starting index of the response.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_SCROLL_KEEP_ALIVE_MS"
 },
     "useScroll": { "kind": "header", "displayName": "", "group": "producer", 
"label": "", "required": false, "javaType": "Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "Set 
to true to enable scroll usage", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_SCROLL" },
     "size": { "kind": "header", "displayName": "", "group": "producer", 
"label": "", "required": false, "javaType": "Integer", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
size of the response.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_SIZE" },
-    "from": { "kind": "header", "displayName": "", "group": "producer", 
"label": "", "required": false, "javaType": "Integer", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
starting index of the response.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_FROM" }
+    "from": { "kind": "header", "displayName": "", "group": "producer", 
"label": "", "required": false, "javaType": "Integer", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
starting index of the response.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_FROM" },
+    "enableDocumentOnlyMode": { "kind": "header", "displayName": "", "group": 
"producer", "label": "", "required": false, "javaType": "Boolean", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "defaultValue": "false", "description": "Indicates whether the body of 
the message contains only documents.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_DOCUMENT_MODE" }
   },
   "properties": {
     "clusterName": { "kind": "path", "displayName": "Cluster Name", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Name of the cluster" },
     "connectionTimeout": { "kind": "parameter", "displayName": "Connection 
Timeout", "group": "producer", "label": "", "required": false, "type": 
"integer", "javaType": "int", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "The time in ms to wait 
before connection will timeout." },
     "disconnect": { "kind": "parameter", "displayName": "Disconnect", "group": 
"producer", "label": "", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Disconnect after it 
finish calling the producer" },
+    "enableDocumentOnlyMode": { "kind": "parameter", "displayName": "Enable 
Document Only Mode", "group": "producer", "label": "", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": false, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Indicates whether the 
body of the message contains only documents. By default, it  [...]
     "from": { "kind": "parameter", "displayName": "From", "group": "producer", 
"label": "", "required": false, "type": "integer", "javaType": 
"java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Starting index of the 
response." },
     "hostAddresses": { "kind": "parameter", "displayName": "Host Addresses", 
"group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Comma separated list 
with ip:port formatted remote transport addresses to use." },
     "indexName": { "kind": "parameter", "displayName": "Index Name", "group": 
"producer", "label": "", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "The name of the index to 
act against" },
diff --git 
a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchComponentConfigurer.java
 
b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchComponentConfigurer.java
index 8b3a0236c01..3cfb3336d9d 100644
--- 
a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchComponentConfigurer.java
+++ 
b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchComponentConfigurer.java
@@ -28,6 +28,8 @@ public class ElasticsearchComponentConfigurer extends 
PropertyConfigurerSupport
         case "client": target.setClient(property(camelContext, 
org.elasticsearch.client.RestClient.class, value)); return true;
         case "connectiontimeout":
         case "connectionTimeout": 
target.setConnectionTimeout(property(camelContext, int.class, value)); return 
true;
+        case "enabledocumentonlymode":
+        case "enableDocumentOnlyMode": 
target.setEnableDocumentOnlyMode(property(camelContext, boolean.class, value)); 
return true;
         case "enablessl":
         case "enableSSL": target.setEnableSSL(property(camelContext, 
boolean.class, value)); return true;
         case "enablesniffer":
@@ -65,6 +67,8 @@ public class ElasticsearchComponentConfigurer extends 
PropertyConfigurerSupport
         case "client": return org.elasticsearch.client.RestClient.class;
         case "connectiontimeout":
         case "connectionTimeout": return int.class;
+        case "enabledocumentonlymode":
+        case "enableDocumentOnlyMode": return boolean.class;
         case "enablessl":
         case "enableSSL": return boolean.class;
         case "enablesniffer":
@@ -98,6 +102,8 @@ public class ElasticsearchComponentConfigurer extends 
PropertyConfigurerSupport
         case "client": return target.getClient();
         case "connectiontimeout":
         case "connectionTimeout": return target.getConnectionTimeout();
+        case "enabledocumentonlymode":
+        case "enableDocumentOnlyMode": return 
target.isEnableDocumentOnlyMode();
         case "enablessl":
         case "enableSSL": return target.isEnableSSL();
         case "enablesniffer":
diff --git 
a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointConfigurer.java
 
b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointConfigurer.java
index 02657933b8d..0efbe912840 100644
--- 
a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointConfigurer.java
+++ 
b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointConfigurer.java
@@ -28,6 +28,8 @@ public class ElasticsearchEndpointConfigurer extends 
PropertyConfigurerSupport i
         case "disconnect": 
target.getConfiguration().setDisconnect(property(camelContext, boolean.class, 
value)); return true;
         case "documentclass":
         case "documentClass": 
target.getConfiguration().setDocumentClass(property(camelContext, 
java.lang.Class.class, value)); return true;
+        case "enabledocumentonlymode":
+        case "enableDocumentOnlyMode": 
target.getConfiguration().setEnableDocumentOnlyMode(property(camelContext, 
boolean.class, value)); return true;
         case "enablessl":
         case "enableSSL": 
target.getConfiguration().setEnableSSL(property(camelContext, boolean.class, 
value)); return true;
         case "enablesniffer":
@@ -69,6 +71,8 @@ public class ElasticsearchEndpointConfigurer extends 
PropertyConfigurerSupport i
         case "disconnect": return boolean.class;
         case "documentclass":
         case "documentClass": return java.lang.Class.class;
+        case "enabledocumentonlymode":
+        case "enableDocumentOnlyMode": return boolean.class;
         case "enablessl":
         case "enableSSL": return boolean.class;
         case "enablesniffer":
@@ -111,6 +115,8 @@ public class ElasticsearchEndpointConfigurer extends 
PropertyConfigurerSupport i
         case "disconnect": return target.getConfiguration().isDisconnect();
         case "documentclass":
         case "documentClass": return 
target.getConfiguration().getDocumentClass();
+        case "enabledocumentonlymode":
+        case "enableDocumentOnlyMode": return 
target.getConfiguration().isEnableDocumentOnlyMode();
         case "enablessl":
         case "enableSSL": return target.getConfiguration().isEnableSSL();
         case "enablesniffer":
diff --git 
a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointUriFactory.java
 
b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointUriFactory.java
index 44fa48f13a9..b192be6c41d 100644
--- 
a/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointUriFactory.java
+++ 
b/components/camel-elasticsearch/src/generated/java/org/apache/camel/component/es/ElasticsearchEndpointUriFactory.java
@@ -21,12 +21,13 @@ public class ElasticsearchEndpointUriFactory extends 
org.apache.camel.support.co
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(20);
+        Set<String> props = new HashSet<>(21);
         props.add("certificatePath");
         props.add("clusterName");
         props.add("connectionTimeout");
         props.add("disconnect");
         props.add("documentClass");
+        props.add("enableDocumentOnlyMode");
         props.add("enableSSL");
         props.add("enableSniffer");
         props.add("from");
diff --git 
a/components/camel-elasticsearch/src/generated/resources/org/apache/camel/component/es/elasticsearch.json
 
b/components/camel-elasticsearch/src/generated/resources/org/apache/camel/component/es/elasticsearch.json
index c3bdd2e6188..81a02fe7d28 100644
--- 
a/components/camel-elasticsearch/src/generated/resources/org/apache/camel/component/es/elasticsearch.json
+++ 
b/components/camel-elasticsearch/src/generated/resources/org/apache/camel/component/es/elasticsearch.json
@@ -23,6 +23,7 @@
   },
   "componentProperties": {
     "connectionTimeout": { "kind": "property", "displayName": "Connection 
Timeout", "group": "producer", "label": "", "required": false, "type": 
"integer", "javaType": "int", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "description": "The time in ms to wait 
before connection will timeout." },
+    "enableDocumentOnlyMode": { "kind": "property", "displayName": "Enable 
Document Only Mode", "group": "producer", "label": "", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": false, "description": "Indicates 
whether the body of the message contains only documents. By default, it is set 
to false to be able to do the same requests as what the Document API supports 
(see https:\/\/www.elastic.co\/guide\ [...]
     "hostAddresses": { "kind": "property", "displayName": "Host Addresses", 
"group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "Comma separated list with ip:port formatted 
remote transport addresses to use. The ip and port options must be left blank 
for hostAddresses to be considered instead." },
     "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start 
Producer", "group": "producer", "label": "producer", "required": false, "type": 
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": false, "description": "Whether the producer 
should be started lazy (on the first message). By starting lazy you can use 
this to allow CamelContext and routes to startup in situations where a producer 
may otherwise fail during star [...]
     "maxRetryTimeout": { "kind": "property", "displayName": "Max Retry 
Timeout", "group": "producer", "label": "", "required": false, "type": 
"integer", "javaType": "int", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "description": "The time in ms before 
retry" },
@@ -46,12 +47,14 @@
     "scrollKeepAliveMs": { "kind": "header", "displayName": "", "group": 
"producer", "label": "", "required": false, "javaType": "Integer", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The starting index of the response.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_SCROLL_KEEP_ALIVE_MS"
 },
     "useScroll": { "kind": "header", "displayName": "", "group": "producer", 
"label": "", "required": false, "javaType": "Boolean", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "Set 
to true to enable scroll usage", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_SCROLL" },
     "size": { "kind": "header", "displayName": "", "group": "producer", 
"label": "", "required": false, "javaType": "Integer", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
size of the response.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_SIZE" },
-    "from": { "kind": "header", "displayName": "", "group": "producer", 
"label": "", "required": false, "javaType": "Integer", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
starting index of the response.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_FROM" }
+    "from": { "kind": "header", "displayName": "", "group": "producer", 
"label": "", "required": false, "javaType": "Integer", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "description": "The 
starting index of the response.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_FROM" },
+    "enableDocumentOnlyMode": { "kind": "header", "displayName": "", "group": 
"producer", "label": "", "required": false, "javaType": "Boolean", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "defaultValue": "false", "description": "Indicates whether the body of 
the message contains only documents.", "constantName": 
"org.apache.camel.component.es.ElasticsearchConstants#PARAM_DOCUMENT_MODE" }
   },
   "properties": {
     "clusterName": { "kind": "path", "displayName": "Cluster Name", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Name of the cluster" },
     "connectionTimeout": { "kind": "parameter", "displayName": "Connection 
Timeout", "group": "producer", "label": "", "required": false, "type": 
"integer", "javaType": "int", "deprecated": false, "autowired": false, 
"secret": false, "defaultValue": 30000, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "The time in ms to wait 
before connection will timeout." },
     "disconnect": { "kind": "parameter", "displayName": "Disconnect", "group": 
"producer", "label": "", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Disconnect after it 
finish calling the producer" },
+    "enableDocumentOnlyMode": { "kind": "parameter", "displayName": "Enable 
Document Only Mode", "group": "producer", "label": "", "required": false, 
"type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": 
false, "secret": false, "defaultValue": false, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Indicates whether the 
body of the message contains only documents. By default, it  [...]
     "from": { "kind": "parameter", "displayName": "From", "group": "producer", 
"label": "", "required": false, "type": "integer", "javaType": 
"java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Starting index of the 
response." },
     "hostAddresses": { "kind": "parameter", "displayName": "Host Addresses", 
"group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "Comma separated list 
with ip:port formatted remote transport addresses to use." },
     "indexName": { "kind": "parameter", "displayName": "Index Name", "group": 
"producer", "label": "", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"configurationClass": 
"org.apache.camel.component.es.ElasticsearchConfiguration", 
"configurationField": "configuration", "description": "The name of the index to 
act against" },
diff --git 
a/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc 
b/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc
index 9d1b0cd25e6..421bd45b91e 100644
--- a/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc
+++ b/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc
@@ -101,8 +101,10 @@ You must set the name of the target index by setting the 
message header with the
 |Update |*byte[]*, *InputStream*, *String*, *Reader*, *Map* or any document 
type content to update |Updates content to an index and returns the content's 
indexId in the body.
 You can set the name of the target index by setting the message header with 
the key "indexName".
 You can set the indexId by setting the message header with
-the key "indexId".
-
+the key "indexId". Be aware of the fact that unlike the component 
_camel-elasticsearch-rest_, by default, the expected content of
+an update request must be the same as what the 
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html[Update
 API expects], consequently
+if you want to update one part of an existing document, you need to embed the 
content to update into a "doc" object. To change the default behavior, it is 
possible
+to configure it globally at the component level thanks to the option 
_enableDocumentOnlyMode_ or by request by setting the header 
_ElasticsearchConstants.PARAM_DOCUMENT_MODE_ to true.
 |Ping |None  |Pings the Elasticsearch cluster and returns true if the ping 
succeeded, false otherwise
 
 |===
@@ -183,7 +185,7 @@ from("direct:search")
 
 [source,java]
 ----
-String query = "{\"query\":{\"match\":{\"doc.content\":\"new release of 
ApacheCamel\"}}}";
+String query = "{\"query\":{\"match\":{\"content\":\"new release of 
ApacheCamel\"}}}";
 HitsMetadata<?> response = template.requestBody("direct:search", query, 
HitsMetadata.class);
 
 ----
@@ -193,7 +195,7 @@ Search on specific field(s) using Map.
 [source,java]
 ----
 Map<String, Object> actualQuery = new HashMap<>();
-actualQuery.put("doc.content", "new release of ApacheCamel");
+actualQuery.put("content", "new release of ApacheCamel");
 
 Map<String, Object> match = new HashMap<>();
 match.put("match", actualQuery);
@@ -222,7 +224,7 @@ from("direct:search")
 
 [source,java]
 ----
-String query = "{\"query\":{\"match\":{\"doc.content\":\"new release of 
ApacheCamel\"}}}";
+String query = "{\"query\":{\"match\":{\"content\":\"new release of 
ApacheCamel\"}}}";
 try (ElasticsearchScrollRequestIterator response = 
template.requestBody("direct:search", query, 
ElasticsearchScrollRequestIterator.class)) {
     // do something smart with results
 }
diff --git 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchComponent.java
 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchComponent.java
index f59751d9257..c46ccc0e9d6 100644
--- 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchComponent.java
+++ 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchComponent.java
@@ -45,6 +45,8 @@ public class ElasticsearchComponent extends DefaultComponent {
     private int maxRetryTimeout = ElasticsearchConstants.MAX_RETRY_TIMEOUT;
     @Metadata(defaultValue = "" + 
ElasticsearchConstants.DEFAULT_CONNECTION_TIMEOUT)
     private int connectionTimeout = 
ElasticsearchConstants.DEFAULT_CONNECTION_TIMEOUT;
+    @Metadata(defaultValue = "false")
+    private boolean enableDocumentOnlyMode;
     @Metadata(label = "security", secret = true)
     private String user;
     @Metadata(label = "security", secret = true)
@@ -84,6 +86,7 @@ public class ElasticsearchComponent extends DefaultComponent {
         config.setSnifferInterval(this.getSnifferInterval());
         config.setSniffAfterFailureDelay(this.getSniffAfterFailureDelay());
         config.setClusterName(remaining);
+        config.setEnableDocumentOnlyMode(this.isEnableDocumentOnlyMode());
 
         Endpoint endpoint = new ElasticsearchEndpoint(uri, this, config, 
client);
         setProperties(endpoint, parameters);
@@ -202,6 +205,21 @@ public class ElasticsearchComponent extends 
DefaultComponent {
         this.certificatePath = certificatePath;
     }
 
+    /**
+     * Indicates whether the body of the message contains only documents. By 
default, it is set to false to be able to
+     * do the same requests as what the Document API supports
+     * (see 
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for 
more details).
+     * To ease the migration of routes based on the legacy component 
camel-elasticsearch-rest, you should consider
+     * enabling the mode especially if your routes do update operations.
+     */
+    public boolean isEnableDocumentOnlyMode() {
+        return enableDocumentOnlyMode;
+    }
+
+    public void setEnableDocumentOnlyMode(boolean enableDocumentOnlyMode) {
+        this.enableDocumentOnlyMode = enableDocumentOnlyMode;
+    }
+
     /**
      * The time in ms before retry
      */
diff --git 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConfiguration.java
 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConfiguration.java
index 34b3676ef86..a6e73b2dd3c 100644
--- 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConfiguration.java
+++ 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConfiguration.java
@@ -53,6 +53,8 @@ public class ElasticsearchConfiguration {
     private int maxRetryTimeout = ElasticsearchConstants.MAX_RETRY_TIMEOUT;
     @UriParam(defaultValue = "" + 
ElasticsearchConstants.DEFAULT_CONNECTION_TIMEOUT)
     private int connectionTimeout = 
ElasticsearchConstants.DEFAULT_CONNECTION_TIMEOUT;
+    @UriParam(defaultValue = "false")
+    private boolean enableDocumentOnlyMode;
     @UriParam
     private boolean disconnect;
     @UriParam(label = "security")
@@ -312,4 +314,19 @@ public class ElasticsearchConfiguration {
     public void setDocumentClass(Class<?> documentClass) {
         this.documentClass = documentClass;
     }
+
+    /**
+     * Indicates whether the body of the message contains only documents. By 
default, it is set to false to be able to
+     * do the same requests as what the Document API supports
+     * (see 
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for 
more details).
+     * To ease the migration of routes based on the legacy component 
camel-elasticsearch-rest, you should consider
+     * enabling the mode especially if your routes do update operations.
+     */
+    public boolean isEnableDocumentOnlyMode() {
+        return enableDocumentOnlyMode;
+    }
+
+    public void setEnableDocumentOnlyMode(boolean enableDocumentOnlyMode) {
+        this.enableDocumentOnlyMode = enableDocumentOnlyMode;
+    }
 }
diff --git 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConstants.java
 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConstants.java
index 40c743ae089..764c1f9a9fb 100644
--- 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConstants.java
+++ 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchConstants.java
@@ -41,6 +41,8 @@ public interface ElasticsearchConstants {
     String PARAM_SIZE = "size";
     @Metadata(description = "The starting index of the response.", javaType = 
"Integer")
     String PARAM_FROM = "from";
+    @Metadata(description = "Indicates whether the body of the message 
contains only documents.", javaType = "Boolean", defaultValue = "false")
+    String PARAM_DOCUMENT_MODE = "enableDocumentOnlyMode";
 
     String PROPERTY_SCROLL_ES_QUERY_COUNT = 
"CamelElasticsearchScrollQueryCount";
 
diff --git 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java
 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java
index 5e5ea1a1787..4b32e179cfc 100644
--- 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java
+++ 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/ElasticsearchProducer.java
@@ -176,6 +176,11 @@ class ElasticsearchProducer extends DefaultAsyncProducer {
                 message.setHeader(ElasticsearchConstants.PARAM_FROM, 
configuration.getFrom());
             }
 
+            Boolean enableDocumentOnlyMode = 
message.getHeader(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.class);
+            if (enableDocumentOnlyMode == null) {
+                message.setHeader(ElasticsearchConstants.PARAM_DOCUMENT_MODE, 
configuration.isEnableDocumentOnlyMode());
+            }
+
             boolean configWaitForActiveShards = false;
             Integer waitForActiveShards = 
message.getHeader(ElasticsearchConstants.PARAM_WAIT_FOR_ACTIVE_SHARDS, 
Integer.class);
             if (waitForActiveShards == null) {
diff --git 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java
 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java
index 19835023e28..4e48992c0c2 100644
--- 
a/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java
+++ 
b/components/camel-elasticsearch/src/main/java/org/apache/camel/component/es/converter/ElasticsearchActionRequestConverter.java
@@ -121,17 +121,19 @@ public final class ElasticsearchActionRequestConverter {
             return 
builder.id(exchange.getIn().getHeader(ElasticsearchConstants.PARAM_INDEX_ID, 
String.class));
         }
         UpdateRequest.Builder<?, Object> builder = new 
UpdateRequest.Builder<>();
+        Boolean enableDocumentOnlyMode = 
exchange.getIn().getHeader(ElasticsearchConstants.PARAM_DOCUMENT_MODE, 
Boolean.FALSE, Boolean.class);
+        Mode mode = enableDocumentOnlyMode == Boolean.TRUE ? 
Mode.DOCUMENT_ONLY : Mode.DEFAULT;
         if (document instanceof byte[]) {
-            builder.withJson(new ByteArrayInputStream((byte[]) document));
+            mode.addDocToUpdateRequestBuilder(builder, new 
ByteArrayInputStream((byte[]) document));
         } else if (document instanceof InputStream) {
-            builder.withJson((InputStream) document);
+            mode.addDocToUpdateRequestBuilder(builder, (InputStream) document);
         } else if (document instanceof String) {
-            builder.withJson(new StringReader((String) document));
+            mode.addDocToUpdateRequestBuilder(builder, new 
StringReader((String) document));
         } else if (document instanceof Reader) {
-            builder.withJson((Reader) document);
+            mode.addDocToUpdateRequestBuilder(builder, (Reader) document);
         } else if (document instanceof Map) {
             ObjectMapper objectMapper = new ObjectMapper();
-            builder.withJson(new 
StringReader(objectMapper.writeValueAsString(document)));
+            mode.addDocToUpdateRequestBuilder(builder, new 
StringReader(objectMapper.writeValueAsString(document)));
         } else {
             builder.doc(document);
         }
@@ -293,4 +295,33 @@ public final class ElasticsearchActionRequestConverter {
         }
         return null;
     }
+
+    enum Mode {
+        DEFAULT {
+            @Override
+            protected void 
addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, 
InputStream in) {
+                builder.withJson(in);
+            }
+
+            @Override
+            protected void 
addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, Reader 
in) {
+                builder.withJson(in);
+            }
+
+        },
+        DOCUMENT_ONLY {
+            @Override
+            protected void 
addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, 
InputStream in) {
+                builder.doc(JsonData.from(in));
+            }
+
+            @Override
+            protected void 
addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, Reader 
in) {
+                builder.doc(JsonData.from(in));
+            }
+        };
+
+        protected abstract void 
addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, 
InputStream in);
+        protected abstract void 
addDocToUpdateRequestBuilder(UpdateRequest.Builder<?, Object> builder, Reader 
in);
+    }
 }
diff --git 
a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchBulkIT.java
 
b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchBulkIT.java
index bd5ab8f5bac..a5bc39e2cbe 100644
--- 
a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchBulkIT.java
+++ 
b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchBulkIT.java
@@ -35,6 +35,7 @@ import 
co.elastic.clients.elasticsearch.core.bulk.DeleteOperation;
 import co.elastic.clients.elasticsearch.core.bulk.IndexOperation;
 import co.elastic.clients.elasticsearch.core.bulk.UpdateAction;
 import co.elastic.clients.elasticsearch.core.bulk.UpdateOperation;
+import co.elastic.clients.json.JsonData;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.camel.builder.RouteBuilder;
 import org.junit.jupiter.api.Test;
@@ -220,10 +221,10 @@ class ElasticsearchBulkIT extends 
ElasticsearchTestSupport {
                 .index("twitter").id(indexId)
                 .action(
                         new UpdateAction.Builder<>()
-                                .withJson(
+                                .doc(JsonData.from(
                                         new StringReader(
-                                                String.format("{ \"doc\": 
{\"%skey2\": \"%svalue2\"}}",
-                                                        createPrefix(), 
createPrefix())))
+                                                String.format("{\"%skey2\": 
\"%svalue2\"}",
+                                                        createPrefix(), 
createPrefix()))))
                                 .build());
         @SuppressWarnings("unchecked")
         List<BulkResponseItem> response = template.requestBody("direct:bulk", 
List.of(builder), List.class);
diff --git 
a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchGetSearchDeleteExistsUpdateIT.java
 
b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchGetSearchDeleteExistsUpdateIT.java
index a6673bf931b..c79fd106865 100644
--- 
a/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchGetSearchDeleteExistsUpdateIT.java
+++ 
b/components/camel-elasticsearch/src/test/java/org/apache/camel/component/es/integration/ElasticsearchGetSearchDeleteExistsUpdateIT.java
@@ -277,12 +277,11 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         Map<String, Object> headers = new HashMap<>();
         headers.put(ElasticsearchConstants.PARAM_OPERATION, 
ElasticsearchOperation.Bulk);
         headers.put(ElasticsearchConstants.PARAM_INDEX_NAME, "twitter");
-        template.requestBodyAndHeaders("direct:start", List.of(Map.of("doc", 
map1), Map.of("doc", map2)), headers,
-                String.class);
+        template.requestBodyAndHeaders("direct:start", List.of(map1, map2), 
headers, String.class);
 
         // No match
         Map<String, Object> actualQuery = new HashMap<>();
-        actualQuery.put("doc.testSearchWithMapQuery1", "bar");
+        actualQuery.put("testSearchWithMapQuery1", "bar");
         Map<String, Object> match = new HashMap<>();
         match.put("match", actualQuery);
         Map<String, Object> query = new HashMap<>();
@@ -293,7 +292,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         assertEquals(0, response.total().value(), "response hits should be == 
0");
 
         // Match
-        actualQuery.put("doc.testSearchWithMapQuery1", "foo");
+        actualQuery.put("testSearchWithMapQuery1", "foo");
         // the result may see stale data so use Awaitility
         Awaitility.await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> {
             HitsMetadata<?> resp = template.requestBody("direct:search", 
query, HitsMetadata.class);
@@ -303,8 +302,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
             assertEquals(1, resp.hits().size(), "response hits should be == 
1");
             Object result = resp.hits().get(0).source();
             assertInstanceOf(ObjectNode.class, result);
-            assertTrue(((ObjectNode) result).has("doc"));
-            JsonNode node = ((ObjectNode) result).get("doc");
+            JsonNode node = (ObjectNode) result;
             assertTrue(node.has("testSearchWithMapQuery1"));
             assertEquals("foo", node.get("testSearchWithMapQuery1").asText());
         });
@@ -318,12 +316,11 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         Map<String, Object> headers = new HashMap<>();
         headers.put(ElasticsearchConstants.PARAM_OPERATION, 
ElasticsearchOperation.Bulk);
         headers.put(ElasticsearchConstants.PARAM_INDEX_NAME, "twitter");
-        template.requestBodyAndHeaders("direct:start", List.of(Map.of("doc", 
map1), Map.of("doc", map2)), headers,
-                String.class);
+        template.requestBodyAndHeaders("direct:start", List.of(map1, map2), 
headers, String.class);
 
         // No match
         String query = "{\n"
-                       + "    \"query\" : { \"match\" : { 
\"doc.testSearchWithStringQuery1\" : \"bar\" }}\n"
+                       + "    \"query\" : { \"match\" : { 
\"testSearchWithStringQuery1\" : \"bar\" }}\n"
                        + "}\n";
 
         HitsMetadata<?> response = template.requestBody("direct:search", 
query, HitsMetadata.class);
@@ -333,7 +330,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
 
         // Match
         String q = "{\n"
-                   + "    \"query\" : { \"match\" : { 
\"doc.testSearchWithStringQuery1\" : \"foo\" }}\n"
+                   + "    \"query\" : { \"match\" : { 
\"testSearchWithStringQuery1\" : \"foo\" }}\n"
                    + "}\n";
         // the result may see stale data so use Awaitility
         Awaitility.await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> {
@@ -344,8 +341,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
             assertEquals(1, resp.hits().size(), "response hits should be == 
1");
             Object result = resp.hits().get(0).source();
             assertInstanceOf(ObjectNode.class, result);
-            assertTrue(((ObjectNode) result).has("doc"));
-            JsonNode node = ((ObjectNode) result).get("doc");
+            JsonNode node = (ObjectNode) result;
             assertTrue(node.has("testSearchWithStringQuery1"));
             assertEquals("foo", 
node.get("testSearchWithStringQuery1").asText());
         });
@@ -359,13 +355,13 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         Map<String, Object> headers = new HashMap<>();
         headers.put(ElasticsearchConstants.PARAM_OPERATION, 
ElasticsearchOperation.Bulk);
         headers.put(ElasticsearchConstants.PARAM_INDEX_NAME, "twitter");
-        template.requestBodyAndHeaders("direct:start", List.of(Map.of("doc", 
map1), Map.of("doc", map2)), headers,
+        template.requestBodyAndHeaders("direct:start", List.of(map1, map2), 
headers,
                 String.class);
 
         // No match
         SearchRequest.Builder builder = new SearchRequest.Builder()
                 .query(new Query.Builder()
-                        .match(new 
MatchQuery.Builder().field("doc.testSearchWithBuilder1").query("bar").build()).build());
+                        .match(new 
MatchQuery.Builder().field("testSearchWithBuilder1").query("bar").build()).build());
         HitsMetadata<?> response = template.requestBody("direct:search", 
builder, HitsMetadata.class);
         assertNotNull(response, "response should not be null");
         assertNotNull(response.total());
@@ -376,7 +372,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         Awaitility.await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> {
             SearchRequest.Builder b = new SearchRequest.Builder()
                     .query(new Query.Builder()
-                            .match(new 
MatchQuery.Builder().field("doc.testSearchWithBuilder1").query("foo").build()).build());
+                            .match(new 
MatchQuery.Builder().field("testSearchWithBuilder1").query("foo").build()).build());
 
             HitsMetadata<?> resp = template.requestBody("direct:search", b, 
HitsMetadata.class);
             assertNotNull(resp, "response should not be null");
@@ -385,8 +381,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
             assertEquals(1, resp.hits().size(), "response hits should be == 
1");
             Object result = resp.hits().get(0).source();
             assertInstanceOf(ObjectNode.class, result);
-            assertTrue(((ObjectNode) result).has("doc"));
-            JsonNode node = ((ObjectNode) result).get("doc");
+            JsonNode node = (ObjectNode) result;
             assertTrue(node.has("testSearchWithBuilder1"));
             assertEquals("foo", node.get("testSearchWithBuilder1").asText());
         });
@@ -415,7 +410,7 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
 
         // No match
         SearchRequest.Builder builder = new SearchRequest.Builder()
-                .query(new Query.Builder().match(new 
MatchQuery.Builder().field("doc.id").query("bar").build()).build());
+                .query(new Query.Builder().match(new 
MatchQuery.Builder().field("id").query("bar").build()).build());
         HitsMetadata<?> response = template.requestBodyAndHeader(
                 "direct:search", builder, 
ElasticsearchConstants.PARAM_DOCUMENT_CLASS, Product.class, HitsMetadata.class);
         assertNotNull(response, "response should not be null");
@@ -534,6 +529,29 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         assertEquals(createPrefix() + "value2", ((ObjectNode) 
response.source()).get(createPrefix() + "key2").asText());
     }
 
+    @Test
+    void testUpdateWithMapInDocumentOnlyMode() {
+        Map<String, String> map = createIndexedData();
+        String indexId = template.requestBody("direct:index", map, 
String.class);
+        assertNotNull(indexId, "indexId should be set");
+
+        Map<String, String> newMap = new HashMap<>();
+        newMap.put(createPrefix() + "key2", createPrefix() + "value2");
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId);
+        headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE);
+        indexId = template.requestBodyAndHeaders("direct:update", newMap, 
headers, String.class);
+        assertNotNull(indexId, "indexId should be set");
+
+        //now, verify GET succeeded
+        GetResponse<?> response = template.requestBody("direct:get", indexId, 
GetResponse.class);
+        assertNotNull(response, "response should not be null");
+        assertNotNull(response.source(), "response source should not be null");
+        assertInstanceOf(ObjectNode.class, response.source(), "response source 
should be a ObjectNode");
+        assertTrue(((ObjectNode) response.source()).has(createPrefix() + 
"key2"));
+        assertEquals(createPrefix() + "value2", ((ObjectNode) 
response.source()).get(createPrefix() + "key2").asText());
+    }
+
     @Test
     void testGetWithHeaders() {
         //first, Index a value
@@ -627,6 +645,26 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         assertEquals("123", indexId, "indexId should be equals to the provided 
id");
     }
 
+    @Test
+    void testUpdateWithIDInHeaderInDocumentOnlyMode() {
+        Map<String, String> map = createIndexedData();
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ElasticsearchConstants.PARAM_OPERATION, 
ElasticsearchOperation.Index);
+        headers.put(ElasticsearchConstants.PARAM_INDEX_NAME, "twitter");
+        headers.put(ElasticsearchConstants.PARAM_INDEX_ID, "123");
+
+        String indexId = template.requestBodyAndHeaders("direct:start", map, 
headers, String.class);
+        assertNotNull(indexId, "indexId should be set");
+        assertEquals("123", indexId, "indexId should be equals to the provided 
id");
+
+        headers.put(ElasticsearchConstants.PARAM_OPERATION, 
ElasticsearchOperation.Update);
+        headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE);
+
+        indexId = template.requestBodyAndHeaders("direct:start", map, headers, 
String.class);
+        assertNotNull(indexId, "indexId should be set");
+        assertEquals("123", indexId, "indexId should be equals to the provided 
id");
+    }
+
     @Test
     void testGetRequestBody() {
         String prefix = createPrefix();
@@ -703,6 +741,27 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         assertThat(node.get(key).asText(), 
equalTo("testUpdateWithString-updated"));
     }
 
+    @Test
+    void testUpdateWithStringInDocumentOnlyMode() {
+        Map<String, String> map = createIndexedData();
+        String indexId = template.requestBody("direct:index", map, 
String.class);
+        assertNotNull(indexId, "indexId should be set");
+        String key = map.keySet().iterator().next();
+        Object body = String.format("{\"%s\" : 
\"testUpdateWithString-updated\"}", key);
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId);
+        headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE);
+        indexId = template.requestBodyAndHeaders("direct:update", body, 
headers, String.class);
+        assertNotNull(indexId, "indexId should be set");
+
+        GetResponse<?> response = template.requestBody("direct:get", indexId, 
GetResponse.class);
+        assertThat(response.source(), notNullValue());
+        ObjectNode node = (ObjectNode) response.source();
+        assertThat(node.has(key), equalTo(true));
+        assertThat(node.get(key).asText(), 
equalTo("testUpdateWithString-updated"));
+    }
+
     @Test
     void testUpdateWithReader() {
         Map<String, String> map = createIndexedData();
@@ -723,6 +782,27 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         assertThat(node.get(key).asText(), 
equalTo("testUpdateWithReader-updated"));
     }
 
+    @Test
+    void testUpdateWithReaderInDocumentOnlyMode() {
+        Map<String, String> map = createIndexedData();
+        String indexId = template.requestBody("direct:index", map, 
String.class);
+        assertNotNull(indexId, "indexId should be set");
+        String key = map.keySet().iterator().next();
+        Object body = new StringReader(String.format("{\"%s\" : 
\"testUpdateWithReader-updated\"}", key));
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId);
+        headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE);
+        indexId = template.requestBodyAndHeaders("direct:update", body, 
headers, String.class);
+        assertNotNull(indexId, "indexId should be set");
+
+        GetResponse<?> response = template.requestBody("direct:get", indexId, 
GetResponse.class);
+        assertThat(response.source(), notNullValue());
+        ObjectNode node = (ObjectNode) response.source();
+        assertThat(node.has(key), equalTo(true));
+        assertThat(node.get(key).asText(), 
equalTo("testUpdateWithReader-updated"));
+    }
+
     @Test
     void testUpdateWithBytes() {
         Map<String, String> map = createIndexedData();
@@ -744,6 +824,28 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         assertThat(node.get(key).asText(), 
equalTo("testUpdateWithBytes-updated"));
     }
 
+    @Test
+    void testUpdateWithBytesInDocumentOnlyMode() {
+        Map<String, String> map = createIndexedData();
+        String indexId = template.requestBody("direct:index", map, 
String.class);
+        assertNotNull(indexId, "indexId should be set");
+        String key = map.keySet().iterator().next();
+        Object body
+                = String.format("{\"%s\" : \"testUpdateWithBytes-updated\"}", 
key).getBytes(StandardCharsets.UTF_8);
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId);
+        headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE);
+        indexId = template.requestBodyAndHeaders("direct:update", body, 
headers, String.class);
+        assertNotNull(indexId, "indexId should be set");
+
+        GetResponse<?> response = template.requestBody("direct:get", indexId, 
GetResponse.class);
+        assertThat(response.source(), notNullValue());
+        ObjectNode node = (ObjectNode) response.source();
+        assertThat(node.has(key), equalTo(true));
+        assertThat(node.get(key).asText(), 
equalTo("testUpdateWithBytes-updated"));
+    }
+
     @Test
     void testUpdateWithInputStream() {
         Map<String, String> map = createIndexedData();
@@ -766,6 +868,29 @@ class ElasticsearchGetSearchDeleteExistsUpdateIT extends 
ElasticsearchTestSuppor
         assertThat(node.get(key).asText(), 
equalTo("testUpdateWithInputStream-updated"));
     }
 
+    @Test
+    void testUpdateWithInputStreamInDocumentOnlyMode() {
+        Map<String, String> map = createIndexedData();
+        String indexId = template.requestBody("direct:index", map, 
String.class);
+        assertNotNull(indexId, "indexId should be set");
+        String key = map.keySet().iterator().next();
+        Object body = new ByteArrayInputStream(
+                String.format("{\"%s\" : 
\"testUpdateWithInputStream-updated\"}", key)
+                        .getBytes(StandardCharsets.UTF_8));
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ElasticsearchConstants.PARAM_INDEX_ID, indexId);
+        headers.put(ElasticsearchConstants.PARAM_DOCUMENT_MODE, Boolean.TRUE);
+        indexId = template.requestBodyAndHeaders("direct:update", body, 
headers, String.class);
+        assertNotNull(indexId, "indexId should be set");
+
+        GetResponse<?> response = template.requestBody("direct:get", indexId, 
GetResponse.class);
+        assertThat(response.source(), notNullValue());
+        ObjectNode node = (ObjectNode) response.source();
+        assertThat(node.has(key), equalTo(true));
+        assertThat(node.get(key).asText(), 
equalTo("testUpdateWithInputStream-updated"));
+    }
+
     @Test
     void testUpdateWithDocumentType() {
         Product product = new Product();
diff --git 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ElasticsearchComponentBuilderFactory.java
 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ElasticsearchComponentBuilderFactory.java
index df50af5eb70..cb4ff5a6e4c 100644
--- 
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ElasticsearchComponentBuilderFactory.java
+++ 
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ElasticsearchComponentBuilderFactory.java
@@ -66,6 +66,25 @@ public interface ElasticsearchComponentBuilderFactory {
             doSetProperty("connectionTimeout", connectionTimeout);
             return this;
         }
+        /**
+         * Indicates whether the body of the message contains only documents. 
By
+         * default, it is set to false to be able to do the same requests as
+         * what the Document API supports (see
+         * 
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for 
more details). To ease the migration of routes based on the legacy component 
camel-elasticsearch-rest, you should consider enabling the mode especially if 
your routes do update operations.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param enableDocumentOnlyMode the value to set
+         * @return the dsl builder
+         */
+        default ElasticsearchComponentBuilder enableDocumentOnlyMode(
+                boolean enableDocumentOnlyMode) {
+            doSetProperty("enableDocumentOnlyMode", enableDocumentOnlyMode);
+            return this;
+        }
         /**
          * Comma separated list with ip:port formatted remote transport
          * addresses to use. The ip and port options must be left blank for
@@ -308,6 +327,7 @@ public interface ElasticsearchComponentBuilderFactory {
                 Object value) {
             switch (name) {
             case "connectionTimeout": ((ElasticsearchComponent) 
component).setConnectionTimeout((int) value); return true;
+            case "enableDocumentOnlyMode": ((ElasticsearchComponent) 
component).setEnableDocumentOnlyMode((boolean) value); return true;
             case "hostAddresses": ((ElasticsearchComponent) 
component).setHostAddresses((java.lang.String) value); return true;
             case "lazyStartProducer": ((ElasticsearchComponent) 
component).setLazyStartProducer((boolean) value); return true;
             case "maxRetryTimeout": ((ElasticsearchComponent) 
component).setMaxRetryTimeout((int) value); return true;
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ElasticsearchEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ElasticsearchEndpointBuilderFactory.java
index 82e50eb4a3d..636c6a61cc2 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ElasticsearchEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ElasticsearchEndpointBuilderFactory.java
@@ -106,6 +106,45 @@ public interface ElasticsearchEndpointBuilderFactory {
             doSetProperty("disconnect", disconnect);
             return this;
         }
+        /**
+         * Indicates whether the body of the message contains only documents. 
By
+         * default, it is set to false to be able to do the same requests as
+         * what the Document API supports (see
+         * 
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for 
more details). To ease the migration of routes based on the legacy component 
camel-elasticsearch-rest, you should consider enabling the mode especially if 
your routes do update operations.
+         * 
+         * The option is a: &lt;code&gt;boolean&lt;/code&gt; type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param enableDocumentOnlyMode the value to set
+         * @return the dsl builder
+         */
+        default ElasticsearchEndpointBuilder enableDocumentOnlyMode(
+                boolean enableDocumentOnlyMode) {
+            doSetProperty("enableDocumentOnlyMode", enableDocumentOnlyMode);
+            return this;
+        }
+        /**
+         * Indicates whether the body of the message contains only documents. 
By
+         * default, it is set to false to be able to do the same requests as
+         * what the Document API supports (see
+         * 
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html for 
more details). To ease the migration of routes based on the legacy component 
camel-elasticsearch-rest, you should consider enabling the mode especially if 
your routes do update operations.
+         * 
+         * The option will be converted to a &lt;code&gt;boolean&lt;/code&gt;
+         * type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @param enableDocumentOnlyMode the value to set
+         * @return the dsl builder
+         */
+        default ElasticsearchEndpointBuilder enableDocumentOnlyMode(
+                String enableDocumentOnlyMode) {
+            doSetProperty("enableDocumentOnlyMode", enableDocumentOnlyMode);
+            return this;
+        }
         /**
          * Starting index of the response.
          * 
@@ -821,6 +860,20 @@ public interface ElasticsearchEndpointBuilderFactory {
         public String from() {
             return "from";
         }
+
+        /**
+         * Indicates whether the body of the message contains only documents.
+         * 
+         * The option is a: {@code Boolean} type.
+         * 
+         * Default: false
+         * Group: producer
+         * 
+         * @return the name of the header {@code enableDocumentOnlyMode}.
+         */
+        public String enableDocumentOnlyMode() {
+            return "enableDocumentOnlyMode";
+        }
     }
     static ElasticsearchEndpointBuilder endpointBuilder(
             String componentName,

Reply via email to