You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2023/09/02 07:06:59 UTC

[camel] branch CAMEL-19752/add-document-only-mode-3.22 created (now cb568809f0a)

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

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


      at cb568809f0a CAMEL-19752: camel-elasticsearch - Add a doc-only mode to ease migration

This branch includes the following new commits:

     new cb568809f0a CAMEL-19752: camel-elasticsearch - Add a doc-only mode to ease migration

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[camel] 01/01: CAMEL-19752: camel-elasticsearch - Add a doc-only mode to ease migration

Posted by nf...@apache.org.
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.22
in repository https://gitbox.apache.org/repos/asf/camel.git

commit cb568809f0a41e0a405cf0385e4f77e9a72ff803
Author: Nicolas Filotto <nf...@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 |   3 +
 .../camel/component/es/ElasticsearchProducer.java  |   5 +
 .../ElasticsearchActionRequestConverter.java       |  43 +++++-
 .../es/integration/ElasticsearchBulkIT.java        |   7 +-
 ...ElasticsearchGetSearchDeleteExistsUpdateIT.java | 161 ++++++++++++++++++---
 .../dsl/ElasticsearchComponentBuilderFactory.java  |  20 +++
 .../dsl/ElasticsearchEndpointBuilderFactory.java   |  53 +++++++
 15 files changed, 330 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 b01989cb483..47457db366e 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 b01989cb483..47457db366e 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 0faff49609e..14e2934ec89 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..9137fcd8f03 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 0cded24d9bc..109a122a709 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")
@@ -313,4 +315,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..c937321e977 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,9 @@ 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 dc13751e598..928c849f88e 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
@@ -175,6 +175,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..4ae90a194df 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,20 @@ 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 +296,34 @@ 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 2cc5c5dbb52..9f3d20022d8 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.
          * 
@@ -822,6 +861,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,