This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch feature/CAMEL-23789-wave1-multi-dsl-docs in repository https://gitbox.apache.org/repos/asf/camel.git
commit c8b363d2b5527631b5c827f3420cb23cc306c7a7 Author: Claus Ibsen <[email protected]> AuthorDate: Wed Jun 17 18:28:58 2026 +0200 CAMEL-23789: Make MongoDB component docs multi-DSL friendly (Wave 1) Resolve all MongoDbConstants to string header values, add Java-only markers for Bson/ProducerTemplate examples, add tabs for count route, fix prose references to use string header names, and remove duplicate projection example. Co-Authored-By: Claude <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../src/main/docs/mongodb-component.adoc | 236 +++++++++++++-------- 1 file changed, 146 insertions(+), 90 deletions(-) diff --git a/components/camel-mongodb/src/main/docs/mongodb-component.adoc b/components/camel-mongodb/src/main/docs/mongodb-component.adoc index 93715a0a4a11..a2455b13f4d7 100644 --- a/components/camel-mongodb/src/main/docs/mongodb-component.adoc +++ b/components/camel-mongodb/src/main/docs/mongodb-component.adoc @@ -229,13 +229,15 @@ YAML:: ====== Example with a query selector (returns the first matching document in a collection): +._Java-only: requires Bson Filters object_ + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:findOneByQuery") - .setHeader(MongoDbConstants.CRITERIA, constant(Filters.eq("name", "Raul Kripalani"))) + .setHeader("CamelMongoDbCriteria", constant(Filters.eq("name", "Raul Kripalani"))) .to("mongodb:myDb?database=flights&collection=tickets&operation=findOneByQuery") .to("mock:resultFindOneByQuery"); ------------------------------------------------------------------------------------- +---- [TIP] ==== @@ -300,24 +302,28 @@ YAML:: ====== Example with a query selector (returns all matching documents in a collection) +._Java-only: requires Bson Filters object_ + [source,java] ------------------------------------------------------------------------------ +---- from("direct:findAll") - .setHeader(MongoDbConstants.CRITERIA, Filters.eq("name", "Raul Kripalani")) + .setHeader("CamelMongoDbCriteria", constant(Filters.eq("name", "Raul Kripalani"))) .to("mongodb:myDb?database=flights&collection=tickets&operation=findAll") .to("mock:resultFindAll"); ------------------------------------------------------------------------------ +---- ====== Example with option _outputType=MongoIterable_ and batch size +._Java-only: requires Bson Filters object_ + [source,java] ------------------------------------------------------------------------------ +---- from("direct:findAll") - .setHeader(MongoDbConstants.BATCH_SIZE).constant(10) - .setHeader(MongoDbConstants.CRITERIA, constant(Filters.eq("name", "Raul Kripalani"))) + .setHeader("CamelMongoDbBatchSize", constant(10)) + .setHeader("CamelMongoDbCriteria", constant(Filters.eq("name", "Raul Kripalani"))) .to("mongodb:myDb?database=flights&collection=tickets&operation=findAll&outputType=MongoIterable") .to("mock:resultFindAll"); ------------------------------------------------------------------------------ +---- [TIP] ==== @@ -337,27 +343,69 @@ and as a result, the operation will not run against the "notableScientists" collection, but against the "dynamicCollectionName" collection. +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------------------------------------------------- +---- from("direct:count") - .to("mongodb:myDb?database=tickets&collection=flights&operation=count&dynamicity=true"); + .to("mongodb:myDb?database=tickets&collection=flights&operation=count&dynamicity=true"); +---- -Long result = template.requestBodyAndHeader("direct:count", "irrelevantBody", MongoDbConstants.COLLECTION, "dynamicCollectionName"); -assertTrue("Result is not of type Long", result instanceof Long); ------------------------------------------------------------------------------------------------------------------------------------- +XML:: ++ +[source,xml] +---- +<route> + <from uri="direct:count"/> + <to uri="mongodb:myDb?database=tickets&collection=flights&operation=count&dynamicity=true"/> +</route> +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:count + steps: + - to: + uri: mongodb:myDb + parameters: + database: tickets + collection: flights + operation: count + dynamicity: true +---- +==== + +To dynamically target a different collection, set the `CamelMongoDbCollection` header: + +._Java-only: Java test API (ProducerTemplate)_ + +[source,java] +---- +Long result = template.requestBodyAndHeader("direct:count", "irrelevantBody", + "CamelMongoDbCollection", "dynamicCollectionName"); +---- You can provide a query *The query object is extracted `CamelMongoDbCriteria` header*. -if the CamelMongoDbCriteria header is null the query object is extracted +if the CamelMongoDbCriteria header is null the query object is extracted message body, i.e., it should be of type `Bson` or convertible to `Bson`., and operation will return the number of documents matching the criteria. +._Java-only: Java test API (ProducerTemplate)_ + [source,java] ------------------------------------------------------------------------------------------------------------------------- +---- Document query = ... -Long count = template.requestBodyAndHeader("direct:count", query, MongoDbConstants.COLLECTION, "dynamicCollectionName"); ------------------------------------------------------------------------------------------------------------------------- +Long count = template.requestBodyAndHeader("direct:count", query, + "CamelMongoDbCollection", "dynamicCollectionName"); +---- ===== Specifying a `fields` filter (projection) @@ -366,30 +414,21 @@ entirety (with all their fields). If your documents are large, and you only require retrieving a subset of their fields, you can specify a field filter in all query operations, simply by setting the relevant `Bson` (or type convertible to `Bson`, such as a JSON String, -Map, etc.) on the `CamelMongoDbFieldsProjection` header, constant shortcut: -`MongoDbConstants.FIELDS_PROJECTION`. +Map, etc.) on the `CamelMongoDbFieldsProjection` header. Here is an example that uses MongoDB's `Projections` to simplify the creation of Bson. It retrieves all fields except `_id` and `boringField`: -[source,java] ----------------------------------------------------------------------------------------------------------------------------- -// route: from("direct:findAll").to("mongodb:myDb?database=flights&collection=tickets&operation=findAll") -Bson fieldProjection = Projection.exclude("_id", "boringField"); -Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, MongoDbConstants.FIELDS_PROJECTION, fieldProjection); ----------------------------------------------------------------------------------------------------------------------------- - -Here is an example that uses MongoDB's `Projections` to simplify -the creation of Bson. It retrieves all fields except `_id` and -`boringField`: +._Java-only: Java test API with Bson Projection_ [source,java] ----------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:findAll").to("mongodb:myDb?database=flights&collection=tickets&operation=findAll") Bson fieldProjection = Projection.exclude("_id", "boringField"); -Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, MongoDbConstants.FIELDS_PROJECTION, fieldProjection); ----------------------------------------------------------------------------------------------------------------------------- +Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, + "CamelMongoDbFieldsProjection", fieldProjection); +---- ===== Specifying a sort clause @@ -399,12 +438,15 @@ that uses MongoDB's `Sorts` to simplify the creation of Bson. It retrieves all fields except `_id` and `boringField`: +._Java-only: Java test API with Bson Sorts_ + [source,java] ----------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:findAll").to("mongodb:myDb?database=flights&collection=tickets&operation=findAll") Bson sorts = Sorts.descending("_id"); -Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, MongoDbConstants.SORT_BY, sorts); ----------------------------------------------------------------------------------------------------------------------------- +Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, + "CamelMongoDbSortBy", sorts); +---- In a Camel route, the SORT_BY header can be used with the findOneByQuery operation to achieve the same result. If the FIELDS_PROJECTION header is also @@ -414,15 +456,17 @@ parameterized MyBatis SELECT query). This example demonstrates fetching the temporally newest document from a collection and reducing the result to a single field, based on the `documentTimestamp` field: +._Java-only: requires Bson Sorts and Projection objects_ + [source,java] ----------------------------------------------------------------------------------------------------------------------------- -.from("direct:someTriggeringEvent") -.setHeader(MongoDbConstants.SORT_BY).constant(Sorts.descending("documentTimestamp")) -.setHeader(MongoDbConstants.FIELDS_PROJECTION).constant(Projection.include("documentTimestamp")) -.setBody().constant("{}") -.to("mongodb:myDb?database=local&collection=myDemoCollection&operation=findOneByQuery") -.to("direct:aMyBatisParameterizedSelect"); ----------------------------------------------------------------------------------------------------------------------------- +---- +from("direct:someTriggeringEvent") + .setHeader("CamelMongoDbSortBy", constant(Sorts.descending("documentTimestamp"))) + .setHeader("CamelMongoDbFieldsProjection", constant(Projection.include("documentTimestamp"))) + .setBody(constant("{}")) + .to("mongodb:myDb?database=local&collection=myDemoCollection&operation=findOneByQuery") + .to("direct:aMyBatisParameterizedSelect"); +---- ==== Create/update operations @@ -496,8 +540,7 @@ expected to ensure at the application level that is unique (and this is a good practice too). OID(s) of the inserted record(s) are stored in the -message header under `CamelMongoOid` key (`MongoDbConstants.OID` -constant). The value stored is `org.bson.types.ObjectId` for single +message header under `CamelMongoOid` key. The value stored is `org.bson.types.ObjectId` for single insert or `java.util.List<org.bson.types.ObjectId>` if multiple records have been inserted. @@ -567,30 +610,32 @@ YAML:: ---- ==== +._Java-only: Java test API (ProducerTemplate)_ + [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:insert").to("mongodb:myDb?database=flights&collection=tickets&operation=save"); -org.bson.Document docForSave = new org.bson.Document(); +Document docForSave = new Document(); docForSave.put("key", "value"); Object result = template.requestBody("direct:insert", docForSave); ------------------------------------------------------------------------------------------------------------------------------------------- +---- ===== update Update one or multiple records in the collection. Requires a filter query and a update rules. -You can define the filter using `MongoDBConstants.CRITERIA` header as `Bson` +You can define the filter using `CamelMongoDbCriteria` header as `Bson` and define the update rules as `Bson` in Body. [NOTE] ==== *Update after enrich* -While defining the filter by using `MongoDBConstants.CRITERIA` header as `Bson` +While defining the filter by using `CamelMongoDbCriteria` header as `Bson` to query mongodb before you do update, you should notice you need to remove it from the resulting Camel exchange during aggregation if you use the enrich pattern with an aggregation strategy and then apply mongodb update. -If you don't remove this header during aggregation and/or redefine `MongoDBConstants.CRITERIA` header before sending +If you don't remove this header during aggregation and/or redefine `CamelMongoDbCriteria` header before sending Camel exchange to mongodb producer endpoint, you may end up with invalid Camel exchange payload while updating mongodb. ==== @@ -614,41 +659,45 @@ records, set the `CamelMongoDbMultiUpdate` IN message header to `true`. ==== -A header with key `CamelMongoDbRecordsAffected` will be returned -(`MongoDbConstants.RECORDS_AFFECTED` constant) with the number of +A header with key `CamelMongoDbRecordsAffected` will be returned with the number of records updated (copied from `WriteResult.getN()`). For example, the following will update *all* records whose filterField field equals true by setting the value of the "scientist" field to "Darwin": +._Java-only: Java test API with Bson filter and update_ + [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:update").to("mongodb:myDb?database=science&collection=notableScientists&operation=update"); List<Bson> body = new ArrayList<>(); Bson filterField = Filters.eq("filterField", true); body.add(filterField); BsonDocument updateObj = new BsonDocument().append("$set", new BsonDocument("scientist", new BsonString("Darwin"))); body.add(updateObj); -Object result = template.requestBodyAndHeader("direct:update", body, MongoDbConstants.MULTIUPDATE, true); ------------------------------------------------------------------------------------------------------------------------------------------- +Object result = template.requestBodyAndHeader("direct:update", body, "CamelMongoDbMultiUpdate", true); +---- + +._Java-only: Java test API with criteria header_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:update").to("mongodb:myDb?database=science&collection=notableScientists&operation=update"); -Maps<String, Object> headers = new HashMap<>(2); -headers.add(MongoDbConstants.MULTIUPDATE, true); -headers.add(MongoDbConstants.FIELDS_FILTER, Filters.eq("filterField", true)); -String updateObj = Updates.set("scientist", "Darwin");; +Map<String, Object> headers = new HashMap<>(2); +headers.put("CamelMongoDbMultiUpdate", true); +headers.put("CamelMongoDbCriteria", Filters.eq("filterField", true)); +Bson updateObj = Updates.set("scientist", "Darwin"); Object result = template.requestBodyAndHeaders("direct:update", updateObj, headers); +---- ------------------------------------------------------------------------------------------------------------------------------------------- +._Java-only: Java test API with JSON string_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:update").to("mongodb:myDb?database=science&collection=notableScientists&operation=update"); String updateObj = "[{\"filterField\": true}, {\"$set\", {\"scientist\", \"Darwin\"}}]"; -Object result = template.requestBodyAndHeader("direct:update", updateObj, MongoDbConstants.MULTIUPDATE, true); +Object result = template.requestBodyAndHeader("direct:update", updateObj, "CamelMongoDbMultiUpdate", true); ------------------------------------------------------------------------------------------------------------------------------------------ @@ -663,15 +712,16 @@ act as the removal filter query, and is expected to be of type 'conditionField' equals true, in the science database, notableScientists collection: +._Java-only: Java test API with Bson filter_ + [source,java] ------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:remove").to("mongodb:myDb?database=science&collection=notableScientists&operation=remove"); Bson conditionField = Filters.eq("conditionField", true); Object result = template.requestBody("direct:remove", conditionField); ------------------------------------------------------------------------------------------------------------------- +---- -A header with key `CamelMongoDbRecordsAffected` is returned -(`MongoDbConstants.RECORDS_AFFECTED` constant) with type `int`, +A header with key `CamelMongoDbRecordsAffected` is returned with type `int`, containing the number of records deleted (copied from `WriteResult.getN()`). @@ -685,17 +735,19 @@ Requires a `List<WriteModel<Document>>` as the IN message body containing comman The following example will insert a new scientist "Pierre Curie", update record with id "5" by setting the value of the "scientist" field to "Marie Curie" and delete record with id "3" : +._Java-only: Java test API with WriteModel objects_ + [source,java] ------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:bulkWrite").to("mongodb:myDb?database=science&collection=notableScientists&operation=bulkWrite"); List<WriteModel<Document>> bulkOperations = Arrays.asList( - new InsertOneModel<>(new Document("scientist", "Pierre Curie")), - new UpdateOneModel<>(new Document("_id", "5"), - new Document("$set", new Document("scientist", "Marie Curie"))), - new DeleteOneModel<>(new Document("_id", "3"))); + new InsertOneModel<>(new Document("scientist", "Pierre Curie")), + new UpdateOneModel<>(new Document("_id", "5"), + new Document("$set", new Document("scientist", "Marie Curie"))), + new DeleteOneModel<>(new Document("_id", "3"))); BulkWriteResult result = template.requestBody("direct:bulkWrite", bulkOperations, BulkWriteResult.class); ------------------------------------------------------------------------------------------------------------------- +---- By default, operations are executed in order and interrupted on the first write error without processing any remaining write operations in the list. To instruct MongoDB to continue to process remaining write operations in the list, set the `CamelMongoDbBulkOrdered` IN message header to `false`. @@ -710,16 +762,18 @@ Perform an aggregation with the given pipeline contained in the body. *Aggregations could be long and heavy operations. Use with care.* +._Java-only: requires Bson aggregation pipeline_ + [source,java] ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:aggregate").to("mongodb:myDb?database=science&collection=notableScientists&operation=aggregate"); -List<Bson> aggregate = Arrays.asList(match(or(eq("scientist", "Darwin"), eq("scientist", +List<Bson> aggregate = Arrays.asList(match(or(eq("scientist", "Darwin"), eq("scientist", "Einstein"))), group("$scientist", sum("count", 1))); from("direct:aggregate") - .setBody().constant(aggregate) + .setBody(constant(aggregate)) .to("mongodb:myDb?database=science&collection=notableScientists&operation=aggregate") .to("mock:resultAggregate"); ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- By default, a List of all results is returned. This can be heavy on memory depending on the size of the results. A safer alternative is to set your outputType=MongoIterable. The next Processor will see an iterable in the message body allowing it to step through the results one by one. @@ -727,13 +781,15 @@ Thus, setting a batch size and returning an iterable allows for efficient retrie An example would look like: +._Java-only: requires Bson aggregation pipeline_ + [source,java] ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -List<Bson> aggregate = Arrays.asList(match(or(eq("scientist", "Darwin"), eq("scientist", +---- +List<Bson> aggregate = Arrays.asList(match(or(eq("scientist", "Darwin"), eq("scientist", "Einstein"))), group("$scientist", sum("count", 1))); from("direct:aggregate") - .setHeader(MongoDbConstants.BATCH_SIZE).constant(10) - .setBody().constant(aggregate) + .setHeader("CamelMongoDbBatchSize", constant(10)) + .setBody(constant(aggregate)) .to("mongodb:myDb?database=science&collection=notableScientists&operation=aggregate&outputType=MongoIterable") .split(body()) .streaming() @@ -836,20 +892,20 @@ Object result = template.requestBody("direct:command", commandBody); ==== Dynamic operations An Exchange can override the endpoint's fixed operation by setting the -`CamelMongoDbOperation` header, defined by the -`MongoDbConstants.OPERATION_HEADER` constant. + - The values supported are determined by the MongoDbOperation enumeration +`CamelMongoDbOperation` header. The values supported are determined by the MongoDbOperation enumeration and match the accepted values for the `operation` parameter on the endpoint URI. For example: +._Java-only: Java test API (ProducerTemplate)_ + [source,java] ------------------------------------------------------------------------------------------------------------------------------ +---- // from("direct:insert").to("mongodb:myDb?database=flights&collection=tickets&operation=insert"); -Object result = template.requestBodyAndHeader("direct:insert", "irrelevantBody", MongoDbConstants.OPERATION_HEADER, "count"); +Object result = template.requestBodyAndHeader("direct:insert", "irrelevantBody", "CamelMongoDbOperation", "count"); assertTrue("Result is not of type Long", result instanceof Long); ------------------------------------------------------------------------------------------------------------------------------ +---- === Consumers There are several types of consumers:
