This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch CAMEL-23218 in repository https://gitbox.apache.org/repos/asf/camel.git
commit a361743933cc4b01f8cedb22ec78c91a07be19d5 Author: Guillaume Nodet <[email protected]> AuthorDate: Thu Mar 19 16:27:29 2026 +0100 CAMEL-23218: Improve docs with migration guide and enhance test coverage - Add migration table showing how to convert view options to SQL++ equivalents - Document both query modes (SQL++ recommended, Views deprecated) - Add test for fullDocument=false (raw query result) mode - Verify HEADER_ID is set correctly in SQL++ consumer - Trim upgrade guide to focus on deprecation notice only Co-Authored-By: Claude Opus 4.6 <[email protected]> --- .../src/main/docs/couchbase-component.adoc | 71 +++++++++++++++++++++- .../couchbase/integration/ConsumeSqlQueryIT.java | 46 +++++++++++--- .../ROOT/pages/camel-4x-upgrade-guide-4_19.adoc | 9 ++- 3 files changed, 111 insertions(+), 15 deletions(-) diff --git a/components/camel-couchbase/src/main/docs/couchbase-component.adoc b/components/camel-couchbase/src/main/docs/couchbase-component.adoc index 6032f18f8bf3..ea909aab8339 100644 --- a/components/camel-couchbase/src/main/docs/couchbase-component.adoc +++ b/components/camel-couchbase/src/main/docs/couchbase-component.adoc @@ -44,10 +44,14 @@ include::partial$component-endpoint-options.adoc[] include::partial$component-endpoint-headers.adoc[] // component options: END -== Consuming with SQL++ (N1QL) queries +== Consuming documents -Since Couchbase Server 7.0, the recommended way to query documents is using SQL++ (formerly N1QL) instead of -MapReduce Views, which are deprecated since Couchbase 7.0 and do not work with the Magma storage backend +The consumer supports two query modes for polling documents from Couchbase: + +=== SQL++ queries (recommended) + +Since Couchbase Server 7.0, the recommended way to query documents is using SQL++ (formerly N1QL). +MapReduce Views are deprecated since Couchbase 7.0 and do not work with the Magma storage backend (default since Couchbase 8.0). To use SQL++ queries, set the `statement` endpoint option: @@ -66,6 +70,67 @@ the document ID. When `false`, the query result row is used directly as the mess NOTE: SQL++ queries require a primary index or appropriate secondary index on the bucket/collection. Create one with: `CREATE PRIMARY INDEX ON \`myBucket\`` or via the Couchbase SDK. +=== MapReduce Views (deprecated) + +The consumer can also poll documents using MapReduce Views via the `designDocumentName` and `viewName` +endpoint options. This mode is deprecated and will be removed in a future release. + +[source,java] +---- +from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" + + "&designDocumentName=myDoc&viewName=myView&limit=10") + .to("direct:result"); +---- + +=== Migrating from Views to SQL++ + +The following table shows how to migrate from MapReduce View options to equivalent SQL++ queries: + +[cols="1,1,2",options="header"] +|=== +| View option | SQL++ equivalent | Example + +| `designDocumentName` + `viewName` +| `statement` +| The view's map function determines what is emitted. Write an equivalent SQL++ query with a `WHERE` clause. + +| `limit=10` +| `LIMIT 10` in the query +| `SELECT META().id AS \__id, * FROM \`bucket\` LIMIT 10` + +| `skip=5` +| `OFFSET 5` in the query +| `SELECT META().id AS \__id, * FROM \`bucket\` LIMIT 10 OFFSET 5` + +| `descending=true` +| `ORDER BY ... DESC` in the query +| `SELECT META().id AS \__id, * FROM \`bucket\` ORDER BY META().id DESC` + +| `rangeStartKey` / `rangeEndKey` +| `WHERE` clause in the query +| `SELECT META().id AS \__id, * FROM \`bucket\` WHERE META().id >= 'start' AND META().id \<= 'end'` + +| `fullDocument=true` +| Works the same way +| When `true`, the consumer fetches the full document via KV get regardless of query mode. +|=== + +For example, a view-based consumer like: + +[source,java] +---- +from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" + + "&designDocumentName=myDoc&viewName=myView&limit=10&descending=true") +---- + +Can be migrated to: + +[source,java] +---- +from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" + + "&statement=SELECT META().id AS __id, * FROM `myBucket` ORDER BY META().id DESC LIMIT 10") +---- + == Couchbase SDK compatibility Using collections and scopes is supported only for Couchbase Server 7.0 and later. diff --git a/components/camel-couchbase/src/test/java/org/apache/camel/component/couchbase/integration/ConsumeSqlQueryIT.java b/components/camel-couchbase/src/test/java/org/apache/camel/component/couchbase/integration/ConsumeSqlQueryIT.java index d97cd6f4e4ef..d8bd01a37b01 100644 --- a/components/camel-couchbase/src/test/java/org/apache/camel/component/couchbase/integration/ConsumeSqlQueryIT.java +++ b/components/camel-couchbase/src/test/java/org/apache/camel/component/couchbase/integration/ConsumeSqlQueryIT.java @@ -23,7 +23,9 @@ import com.couchbase.client.java.Cluster; import com.couchbase.client.java.manager.bucket.BucketSettings; import com.couchbase.client.java.manager.bucket.BucketType; import com.couchbase.client.java.manager.query.CreatePrimaryQueryIndexOptions; +import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.couchbase.CouchbaseConstants; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.infra.common.TestUtils; import org.apache.camel.test.infra.couchbase.services.CouchbaseService; @@ -39,6 +41,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIfSystemProperty; import org.junit.jupiter.api.extension.RegisterExtension; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + @DisabledIfSystemProperty(named = "ci.env.name", matches = ".*", disabledReason = "Too resource intensive for most systems to run reliably") @Tags({ @Tag("couchbase-71") }) @@ -79,11 +84,33 @@ public class ConsumeSqlQueryIT extends CamelTestSupport { } @Test - public void testConsumeWithSqlQuery() throws Exception { - MockEndpoint mock = getMockEndpoint("mock:result"); - mock.expectedMessageCount(10); + public void testConsumeWithSqlQueryAndFullDocument() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:fullDoc"); + mock.expectedMinimumMessageCount(10); + + MockEndpoint.assertIsSatisfied(context, 30, TimeUnit.SECONDS); + + // Verify headers are set correctly + for (Exchange exchange : mock.getReceivedExchanges()) { + String id = exchange.getIn().getHeader(CouchbaseConstants.HEADER_ID, String.class); + assertNotNull(id, "Document ID header should be set"); + assertTrue(id.startsWith("DocumentID_"), "Document ID should match inserted documents"); + } + } + + @Test + public void testConsumeWithSqlQueryRawResult() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:raw"); + mock.expectedMinimumMessageCount(5); MockEndpoint.assertIsSatisfied(context, 30, TimeUnit.SECONDS); + + // With fullDocument=false, body should be the SQL++ query result row (a JSON string) + for (Exchange exchange : mock.getReceivedExchanges()) { + Object body = exchange.getIn().getBody(); + assertNotNull(body, "Body should not be null"); + assertTrue(body instanceof String, "Body should be a String (JSON row)"); + } } @AfterEach @@ -107,10 +134,15 @@ public class ConsumeSqlQueryIT extends CamelTestSupport { return new RouteBuilder() { @Override public void configure() { - String query = "SELECT META().id AS __id, * FROM `" + bucketName + "` LIMIT 10"; - from(getConnectionUri() + "&statement=" + query) - .log("message received via SQL++") - .to("mock:result"); + // SQL++ with fullDocument=true (default) — fetches complete document via KV get + String fullDocQuery = "SELECT META().id AS __id, * FROM `" + bucketName + "` LIMIT 10"; + from(getConnectionUri() + "&statement=" + fullDocQuery) + .to("mock:fullDoc"); + + // SQL++ with fullDocument=false — uses raw query result row as body + String rawQuery = "SELECT META().id AS __id, * FROM `" + bucketName + "` LIMIT 5"; + from(getConnectionUri() + "&statement=" + rawQuery + "&fullDocument=false") + .to("mock:raw"); } }; } diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc index 39fdb2a5cdd2..bd1f030c5aca 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc @@ -401,13 +401,12 @@ HttpRequest request = context.getRequest(); === camel-couchbase -The consumer now supports SQL++ (N1QL) queries as an alternative to the deprecated MapReduce Views. -Use the new `statement` endpoint option to specify a SQL++ query. When `statement` is set, the consumer -uses `scope.query()` instead of `bucket.viewQuery()`. - The `designDocumentName` and `viewName` endpoint options are now deprecated. MapReduce Views were deprecated in Couchbase Server 7.0 and do not work with the Magma storage backend (default since -Couchbase Server 8.0). Users should migrate to SQL++ queries using the `statement` option. +Couchbase Server 8.0). + +A new `statement` endpoint option has been added to support SQL++ (N1QL) queries as the recommended +alternative. See the component documentation for migration guidance. === camel-ftp
