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

gnodet pushed a commit to branch hungry-quark
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 14b82dbf162207c5918c2019db84be777f156444
Author: Guillaume Nodet <[email protected]>
AuthorDate: Mon Mar 23 21:52:50 2026 +0100

    CAMEL-21540: Add PGVector component for PostgreSQL vector database
    
    - New camel-pgvector component under components/camel-ai/
    - Supports CREATE_TABLE, DROP_TABLE, UPSERT, DELETE, SIMILARITY_SEARCH 
actions
    - Uses PostgreSQL pgvector extension via JDBC with com.pgvector library
    - Supports cosine, euclidean, and inner product distance types
    - LangChain4j data type transformers: pgvector:embeddings and pgvector:rag
    - Integration tests with testcontainers pgvector image
    - LangChain4j embeddings integration test with AllMiniLmL6V2 model
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 catalog/camel-allcomponents/pom.xml                |   5 +
 .../camel-ai/camel-langchain4j-embeddings/pom.xml  |  11 +
 ...Chain4jEmbeddingsComponentPgVectorTargetIT.java | 141 ++++++++++++
 components/camel-ai/camel-pgvector/pom.xml         |  90 ++++++++
 .../pgvector/PgVectorComponentConfigurer.java      |  87 ++++++++
 .../pgvector/PgVectorConfigurationConfigurer.java  |  60 ++++++
 .../pgvector/PgVectorEndpointConfigurer.java       |  71 ++++++
 .../pgvector/PgVectorEndpointUriFactory.java       |  74 +++++++
 .../apache/camel/component/pgvector/pgvector.json  |  48 +++++
 .../services/org/apache/camel/component.properties |   7 +
 .../services/org/apache/camel/component/pgvector   |   2 +
 ....camel.component.pgvector.PgVectorConfiguration |   2 +
 .../org/apache/camel/configurer/pgvector-component |   2 +
 .../org/apache/camel/configurer/pgvector-endpoint  |   2 +
 .../org/apache/camel/transformer.properties        |   7 +
 .../apache/camel/transformer/pgvector-embeddings   |   2 +
 .../camel/transformer/pgvector-embeddings.json     |  14 ++
 .../org/apache/camel/transformer/pgvector-rag      |   2 +
 .../org/apache/camel/transformer/pgvector-rag.json |  14 ++
 .../org/apache/camel/urifactory/pgvector-endpoint  |   2 +
 .../src/main/docs/pgvector-component.adoc          |  60 ++++++
 .../apache/camel/component/pgvector/PgVector.java  |  24 +++
 .../camel/component/pgvector/PgVectorAction.java   |  25 +++
 .../component/pgvector/PgVectorComponent.java      |  68 ++++++
 .../component/pgvector/PgVectorConfiguration.java  | 100 +++++++++
 .../camel/component/pgvector/PgVectorEndpoint.java |  97 +++++++++
 .../camel/component/pgvector/PgVectorHeaders.java  |  44 ++++
 .../camel/component/pgvector/PgVectorProducer.java | 238 +++++++++++++++++++++
 .../PgVectorEmbeddingsDataTypeTransformer.java     |  76 +++++++
 ...VectorReverseEmbeddingsDataTypeTransformer.java |  46 ++++
 .../component/pgvector/PgVectorComponentIT.java    | 191 +++++++++++++++++
 components/camel-ai/pom.xml                        |   1 +
 parent/pom.xml                                     |   6 +
 .../apache/camel/maven/packaging/MojoHelper.java   |   2 +-
 34 files changed, 1620 insertions(+), 1 deletion(-)

diff --git a/catalog/camel-allcomponents/pom.xml 
b/catalog/camel-allcomponents/pom.xml
index 7f8782e412b6..65d277816e81 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -1682,6 +1682,11 @@
             <artifactId>camel-pgevent</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-pgvector</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-pinecone</artifactId>
diff --git a/components/camel-ai/camel-langchain4j-embeddings/pom.xml 
b/components/camel-ai/camel-langchain4j-embeddings/pom.xml
index 9ea004fe94ca..9993ff4d8825 100644
--- a/components/camel-ai/camel-langchain4j-embeddings/pom.xml
+++ b/components/camel-ai/camel-langchain4j-embeddings/pom.xml
@@ -87,6 +87,11 @@
             <artifactId>camel-milvus</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-pgvector</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-pinecone</artifactId>
@@ -156,6 +161,12 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-postgres</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-test-infra-weaviate</artifactId>
diff --git 
a/components/camel-ai/camel-langchain4j-embeddings/src/test/java/org/apache/camel/component/langchain4j/embeddings/LangChain4jEmbeddingsComponentPgVectorTargetIT.java
 
b/components/camel-ai/camel-langchain4j-embeddings/src/test/java/org/apache/camel/component/langchain4j/embeddings/LangChain4jEmbeddingsComponentPgVectorTargetIT.java
new file mode 100644
index 000000000000..cb1f75b825ef
--- /dev/null
+++ 
b/components/camel-ai/camel-langchain4j-embeddings/src/test/java/org/apache/camel/component/langchain4j/embeddings/LangChain4jEmbeddingsComponentPgVectorTargetIT.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.langchain4j.embeddings;
+
+import java.util.List;
+
+import 
dev.langchain4j.model.embedding.onnx.allminilml6v2.AllMiniLmL6V2EmbeddingModel;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.pgvector.PgVector;
+import org.apache.camel.component.pgvector.PgVectorAction;
+import org.apache.camel.component.pgvector.PgVectorComponent;
+import org.apache.camel.component.pgvector.PgVectorHeaders;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.test.infra.postgres.services.PostgresService;
+import 
org.apache.camel.test.infra.postgres.services.PostgresVectorServiceFactory;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.postgresql.ds.PGSimpleDataSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class LangChain4jEmbeddingsComponentPgVectorTargetIT extends 
CamelTestSupport {
+
+    public static final String PGVECTOR_URI = "pgvector:embeddings";
+
+    @RegisterExtension
+    static PostgresService POSTGRES = 
PostgresVectorServiceFactory.createService();
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+
+        PGSimpleDataSource dataSource = new PGSimpleDataSource();
+        dataSource.setUrl(POSTGRES.jdbcUrl());
+        dataSource.setUser(POSTGRES.userName());
+        dataSource.setPassword(POSTGRES.password());
+
+        PgVectorComponent component = context.getComponent(PgVector.SCHEME, 
PgVectorComponent.class);
+        component.getConfiguration().setDataSource(dataSource);
+        context.getRegistry().bind("embedding-model", new 
AllMiniLmL6V2EmbeddingModel());
+
+        return context;
+    }
+
+    @Test
+    @Order(1)
+    public void createTable() {
+        Exchange result = fluentTemplate.to(PGVECTOR_URI)
+                .withHeader(PgVectorHeaders.ACTION, 
PgVectorAction.CREATE_TABLE)
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+    }
+
+    @Test
+    @Order(2)
+    public void upsertEmbedding() {
+        Exchange result = fluentTemplate.to("direct:in")
+                .withHeader(PgVectorHeaders.ACTION, PgVectorAction.UPSERT)
+                .withHeader(PgVectorHeaders.RECORD_ID, "embed-1")
+                .withBody("The sky is blue")
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+        
assertThat(result.getMessage().getBody(String.class)).isEqualTo("embed-1");
+    }
+
+    @Test
+    @Order(3)
+    public void upsertSecondEmbedding() {
+        Exchange result = fluentTemplate.to("direct:in")
+                .withHeader(PgVectorHeaders.ACTION, PgVectorAction.UPSERT)
+                .withHeader(PgVectorHeaders.RECORD_ID, "embed-2")
+                .withBody("The ocean is deep")
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+    }
+
+    @Test
+    @Order(4)
+    @SuppressWarnings("unchecked")
+    public void queryEmbeddings() {
+        Exchange result = fluentTemplate.to("direct:query")
+                .withHeader(PgVectorHeaders.ACTION, 
PgVectorAction.SIMILARITY_SEARCH)
+                .withBody("blue sky")
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+
+        List<String> results = result.getMessage().getBody(List.class);
+        assertThat(results).isNotEmpty();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:in")
+                        .to("langchain4j-embeddings:test")
+                        .transformDataType(new DataType("pgvector:embeddings"))
+                        .to(PGVECTOR_URI);
+
+                from("direct:query")
+                        .to("langchain4j-embeddings:test")
+                        .transformDataType(new DataType("pgvector:embeddings"))
+                        .setHeader(PgVectorHeaders.ACTION, 
constant(PgVectorAction.SIMILARITY_SEARCH))
+                        .to(PGVECTOR_URI)
+                        .transformDataType(new DataType("pgvector:rag"));
+            }
+        };
+    }
+}
diff --git a/components/camel-ai/camel-pgvector/pom.xml 
b/components/camel-ai/camel-pgvector/pom.xml
new file mode 100644
index 000000000000..b02e9208d361
--- /dev/null
+++ b/components/camel-ai/camel-pgvector/pom.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>camel-ai-parent</artifactId>
+        <groupId>org.apache.camel</groupId>
+        <version>4.19.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-pgvector</artifactId>
+    <packaging>jar</packaging>
+    <name>Camel :: AI :: PGVector</name>
+    <description>Camel PGVector support</description>
+
+    <properties>
+        <camel.surefire.parallel>true</camel.surefire.parallel>
+        <camel.surefire.parallel.factor>4</camel.surefire.parallel.factor>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-core</artifactId>
+            <version>${langchain4j-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>${pgjdbc-driver-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.pgvector</groupId>
+            <artifactId>pgvector</artifactId>
+            <version>${pgvector-version}</version>
+        </dependency>
+
+        <!-- test infra -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-postgres</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- test dependencies -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-junit6</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorComponentConfigurer.java
 
b/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorComponentConfigurer.java
new file mode 100644
index 000000000000..c9b6b44f7636
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorComponentConfigurer.java
@@ -0,0 +1,87 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.pgvector;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class PgVectorComponentConfigurer extends PropertyConfigurerSupport 
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    private org.apache.camel.component.pgvector.PgVectorConfiguration 
getOrCreateConfiguration(PgVectorComponent target) {
+        if (target.getConfiguration() == null) {
+            target.setConfiguration(new 
org.apache.camel.component.pgvector.PgVectorConfiguration());
+        }
+        return target.getConfiguration();
+    }
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        PgVectorComponent target = (PgVectorComponent) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "autowiredenabled":
+        case "autowiredEnabled": 
target.setAutowiredEnabled(property(camelContext, boolean.class, value)); 
return true;
+        case "configuration": target.setConfiguration(property(camelContext, 
org.apache.camel.component.pgvector.PgVectorConfiguration.class, value)); 
return true;
+        case "datasource":
+        case "dataSource": 
getOrCreateConfiguration(target).setDataSource(property(camelContext, 
javax.sql.DataSource.class, value)); return true;
+        case "dimension": 
getOrCreateConfiguration(target).setDimension(property(camelContext, int.class, 
value)); return true;
+        case "distancetype":
+        case "distanceType": 
getOrCreateConfiguration(target).setDistanceType(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": 
target.setLazyStartProducer(property(camelContext, boolean.class, value)); 
return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public String[] getAutowiredNames() {
+        return new String[]{"dataSource"};
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "autowiredenabled":
+        case "autowiredEnabled": return boolean.class;
+        case "configuration": return 
org.apache.camel.component.pgvector.PgVectorConfiguration.class;
+        case "datasource":
+        case "dataSource": return javax.sql.DataSource.class;
+        case "dimension": return int.class;
+        case "distancetype":
+        case "distanceType": return java.lang.String.class;
+        case "lazystartproducer":
+        case "lazyStartProducer": return boolean.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        PgVectorComponent target = (PgVectorComponent) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "autowiredenabled":
+        case "autowiredEnabled": return target.isAutowiredEnabled();
+        case "configuration": return target.getConfiguration();
+        case "datasource":
+        case "dataSource": return 
getOrCreateConfiguration(target).getDataSource();
+        case "dimension": return 
getOrCreateConfiguration(target).getDimension();
+        case "distancetype":
+        case "distanceType": return 
getOrCreateConfiguration(target).getDistanceType();
+        case "lazystartproducer":
+        case "lazyStartProducer": return target.isLazyStartProducer();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorConfigurationConfigurer.java
 
b/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorConfigurationConfigurer.java
new file mode 100644
index 000000000000..8bedda0cef91
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorConfigurationConfigurer.java
@@ -0,0 +1,60 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.pgvector;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.component.pgvector.PgVectorConfiguration;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateConfigurerMojo")
+@SuppressWarnings("unchecked")
+public class PgVectorConfigurationConfigurer extends 
org.apache.camel.support.component.PropertyConfigurerSupport implements 
GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        org.apache.camel.component.pgvector.PgVectorConfiguration target = 
(org.apache.camel.component.pgvector.PgVectorConfiguration) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "datasource":
+        case "dataSource": target.setDataSource(property(camelContext, 
javax.sql.DataSource.class, value)); return true;
+        case "dimension": target.setDimension(property(camelContext, 
int.class, value)); return true;
+        case "distancetype":
+        case "distanceType": target.setDistanceType(property(camelContext, 
java.lang.String.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "datasource":
+        case "dataSource": return javax.sql.DataSource.class;
+        case "dimension": return int.class;
+        case "distancetype":
+        case "distanceType": return java.lang.String.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.component.pgvector.PgVectorConfiguration target = 
(org.apache.camel.component.pgvector.PgVectorConfiguration) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "datasource":
+        case "dataSource": return target.getDataSource();
+        case "dimension": return target.getDimension();
+        case "distancetype":
+        case "distanceType": return target.getDistanceType();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorEndpointConfigurer.java
 
b/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorEndpointConfigurer.java
new file mode 100644
index 000000000000..faa4cd792493
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorEndpointConfigurer.java
@@ -0,0 +1,71 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.pgvector;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class PgVectorEndpointConfigurer extends PropertyConfigurerSupport 
implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        PgVectorEndpoint target = (PgVectorEndpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "datasource":
+        case "dataSource": 
target.getConfiguration().setDataSource(property(camelContext, 
javax.sql.DataSource.class, value)); return true;
+        case "dimension": 
target.getConfiguration().setDimension(property(camelContext, int.class, 
value)); return true;
+        case "distancetype":
+        case "distanceType": 
target.getConfiguration().setDistanceType(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": 
target.setLazyStartProducer(property(camelContext, boolean.class, value)); 
return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public String[] getAutowiredNames() {
+        return new String[]{"dataSource"};
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "datasource":
+        case "dataSource": return javax.sql.DataSource.class;
+        case "dimension": return int.class;
+        case "distancetype":
+        case "distanceType": return java.lang.String.class;
+        case "lazystartproducer":
+        case "lazyStartProducer": return boolean.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        PgVectorEndpoint target = (PgVectorEndpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "datasource":
+        case "dataSource": return target.getConfiguration().getDataSource();
+        case "dimension": return target.getConfiguration().getDimension();
+        case "distancetype":
+        case "distanceType": return 
target.getConfiguration().getDistanceType();
+        case "lazystartproducer":
+        case "lazyStartProducer": return target.isLazyStartProducer();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorEndpointUriFactory.java
 
b/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorEndpointUriFactory.java
new file mode 100644
index 000000000000..c41db64d0fcb
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/java/org/apache/camel/component/pgvector/PgVectorEndpointUriFactory.java
@@ -0,0 +1,74 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.pgvector;
+
+import javax.annotation.processing.Generated;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.spi.EndpointUriFactory;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateEndpointUriFactoryMojo")
+public class PgVectorEndpointUriFactory extends 
org.apache.camel.support.component.EndpointUriFactorySupport implements 
EndpointUriFactory {
+
+    private static final String BASE = ":collection";
+
+    private static final Set<String> PROPERTY_NAMES;
+    private static final Set<String> SECRET_PROPERTY_NAMES;
+    private static final Map<String, String> MULTI_VALUE_PREFIXES;
+    static {
+        Set<String> props = new HashSet<>(5);
+        props.add("collection");
+        props.add("dataSource");
+        props.add("dimension");
+        props.add("distanceType");
+        props.add("lazyStartProducer");
+        PROPERTY_NAMES = Collections.unmodifiableSet(props);
+        SECRET_PROPERTY_NAMES = Collections.emptySet();
+        MULTI_VALUE_PREFIXES = Collections.emptyMap();
+    }
+
+    @Override
+    public boolean isEnabled(String scheme) {
+        return "pgvector".equals(scheme);
+    }
+
+    @Override
+    public String buildUri(String scheme, Map<String, Object> properties, 
boolean encode) throws URISyntaxException {
+        String syntax = scheme + BASE;
+        String uri = syntax;
+
+        Map<String, Object> copy = new HashMap<>(properties);
+
+        uri = buildPathParameter(syntax, uri, "collection", null, true, copy);
+        uri = buildQueryParameters(uri, copy, encode);
+        return uri;
+    }
+
+    @Override
+    public Set<String> propertyNames() {
+        return PROPERTY_NAMES;
+    }
+
+    @Override
+    public Set<String> secretPropertyNames() {
+        return SECRET_PROPERTY_NAMES;
+    }
+
+    @Override
+    public Map<String, String> multiValuePrefixes() {
+        return MULTI_VALUE_PREFIXES;
+    }
+
+    @Override
+    public boolean isLenientProperties() {
+        return false;
+    }
+}
+
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/org/apache/camel/component/pgvector/pgvector.json
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/org/apache/camel/component/pgvector/pgvector.json
new file mode 100644
index 000000000000..69d46599f91e
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/org/apache/camel/component/pgvector/pgvector.json
@@ -0,0 +1,48 @@
+{
+  "component": {
+    "kind": "component",
+    "name": "pgvector",
+    "title": "PGVector",
+    "description": "Perform operations on the PostgreSQL pgvector Vector 
Database.",
+    "deprecated": false,
+    "firstVersion": "4.19.0",
+    "label": "database,ai",
+    "javaType": "org.apache.camel.component.pgvector.PgVectorComponent",
+    "supportLevel": "Preview",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-pgvector",
+    "version": "4.19.0-SNAPSHOT",
+    "scheme": "pgvector",
+    "extendsScheme": "",
+    "syntax": "pgvector:collection",
+    "async": false,
+    "api": false,
+    "consumerOnly": false,
+    "producerOnly": true,
+    "lenientProperties": false,
+    "browsable": false,
+    "remote": true
+  },
+  "componentProperties": {
+    "configuration": { "index": 0, "kind": "property", "displayName": 
"Configuration", "group": "producer", "label": "", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.pgvector.PgVectorConfiguration", "deprecated": 
false, "autowired": false, "secret": false, "description": "The configuration;" 
},
+    "dataSource": { "index": 1, "kind": "property", "displayName": "Data 
Source", "group": "producer", "label": "", "required": false, "type": "object", 
"javaType": "javax.sql.DataSource", "deprecated": false, "deprecationNote": "", 
"autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pgvector.PgVectorConfiguration", 
"configurationField": "configuration", "description": "The DataSource to use 
for connecting to the PostgreSQL database with pgvector extension." },
+    "dimension": { "index": 2, "kind": "property", "displayName": "Dimension", 
"group": "producer", "label": "producer", "required": false, "type": "integer", 
"javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "defaultValue": 384, "configurationClass": 
"org.apache.camel.component.pgvector.PgVectorConfiguration", 
"configurationField": "configuration", "description": "The dimension of the 
vectors to store." },
+    "distanceType": { "index": 3, "kind": "property", "displayName": "Distance 
Type", "group": "producer", "label": "producer", "required": false, "type": 
"string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"cosine", "configurationClass": 
"org.apache.camel.component.pgvector.PgVectorConfiguration", 
"configurationField": "configuration", "description": "The distance type to use 
for similarity search." },
+    "lazyStartProducer": { "index": 4, "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 [...]
+    "autowiredEnabled": { "index": 5, "kind": "property", "displayName": 
"Autowired Enabled", "group": "advanced", "label": "advanced", "required": 
false, "type": "boolean", "javaType": "boolean", "deprecated": false, 
"autowired": false, "secret": false, "defaultValue": true, "description": 
"Whether autowiring is enabled. This is used for automatic autowiring options 
(the option must be marked as autowired) by looking up in the registry to find 
if there is a single instance of matching t [...]
+  },
+  "headers": {
+    "CamelPgVectorAction": { "index": 0, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"enum": [ "CREATE_TABLE", "DROP_TABLE", "UPSERT", "DELETE", "SIMILARITY_SEARCH" 
], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The action to be performed.", "constantName": 
"org.apache.camel.component.pgvector.PgVectorHeaders#ACTION" },
+    "CamelPgVectorRecordId": { "index": 1, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The id of the vector record.", "constantName": 
"org.apache.camel.component.pgvector.PgVectorHeaders#RECORD_ID" },
+    "CamelPgVectorQueryTopK": { "index": 2, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "Integer", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "defaultValue": "3", "description": "The maximum number of results to 
return for similarity search.", "constantName": 
"org.apache.camel.component.pgvector.PgVectorHeaders#QUERY_TOP_K" },
+    "CamelPgVectorTextContent": { "index": 3, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The text content to store alongside the vector 
embedding.", "constantName": 
"org.apache.camel.component.pgvector.PgVectorHeaders#TEXT_CONTENT" },
+    "CamelPgVectorMetadata": { "index": 4, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The metadata associated with the vector record, stored 
as JSON.", "constantName": 
"org.apache.camel.component.pgvector.PgVectorHeaders#METADATA" }
+  },
+  "properties": {
+    "collection": { "index": 0, "kind": "path", "displayName": "Collection", 
"group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "description": "The collection (table) 
name" },
+    "dataSource": { "index": 1, "kind": "parameter", "displayName": "Data 
Source", "group": "producer", "label": "", "required": false, "type": "object", 
"javaType": "javax.sql.DataSource", "deprecated": false, "deprecationNote": "", 
"autowired": true, "secret": false, "configurationClass": 
"org.apache.camel.component.pgvector.PgVectorConfiguration", 
"configurationField": "configuration", "description": "The DataSource to use 
for connecting to the PostgreSQL database with pgvector extens [...]
+    "dimension": { "index": 2, "kind": "parameter", "displayName": 
"Dimension", "group": "producer", "label": "producer", "required": false, 
"type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": 
"", "autowired": false, "secret": false, "defaultValue": 384, 
"configurationClass": 
"org.apache.camel.component.pgvector.PgVectorConfiguration", 
"configurationField": "configuration", "description": "The dimension of the 
vectors to store." },
+    "distanceType": { "index": 3, "kind": "parameter", "displayName": 
"Distance Type", "group": "producer", "label": "producer", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 
"cosine", "configurationClass": 
"org.apache.camel.component.pgvector.PgVectorConfiguration", 
"configurationField": "configuration", "description": "The distance type to use 
for similarity search." },
+    "lazyStartProducer": { "index": 4, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "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 produc [...]
+  }
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/component.properties
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 000000000000..cad7e0ed6691
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+components=pgvector
+groupId=org.apache.camel
+artifactId=camel-pgvector
+version=4.19.0-SNAPSHOT
+projectName=Camel :: AI :: PGVector
+projectDescription=Camel PGVector support
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/component/pgvector
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/component/pgvector
new file mode 100644
index 000000000000..3945951638c5
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/component/pgvector
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.pgvector.PgVectorComponent
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.pgvector.PgVectorConfiguration
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.pgvector.PgVectorConfiguration
new file mode 100644
index 000000000000..cf12de7c025d
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.pgvector.PgVectorConfiguration
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.pgvector.PgVectorConfigurationConfigurer
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/pgvector-component
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/pgvector-component
new file mode 100644
index 000000000000..fd431f002970
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/pgvector-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.pgvector.PgVectorComponentConfigurer
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/pgvector-endpoint
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/pgvector-endpoint
new file mode 100644
index 000000000000..483f077e2040
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/configurer/pgvector-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.pgvector.PgVectorEndpointConfigurer
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
new file mode 100644
index 000000000000..27a4f45b1c78
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+transformers=pgvector:embeddings pgvector:rag
+groupId=org.apache.camel
+artifactId=camel-pgvector
+version=4.19.0-SNAPSHOT
+projectName=Camel :: AI :: PGVector
+projectDescription=Camel PGVector support
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-embeddings
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-embeddings
new file mode 100644
index 000000000000..4b6963457fb0
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-embeddings
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.pgvector.transform.PgVectorEmbeddingsDataTypeTransformer
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-embeddings.json
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-embeddings.json
new file mode 100644
index 000000000000..2a5efd26fd33
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-embeddings.json
@@ -0,0 +1,14 @@
+{
+  "transformer": {
+    "kind": "transformer",
+    "name": "pgvector:embeddings",
+    "title": "Pgvector (Embeddings)",
+    "description": "Prepares the message to become an object writable by 
PgVector component",
+    "deprecated": false,
+    "javaType": 
"org.apache.camel.component.pgvector.transform.PgVectorEmbeddingsDataTypeTransformer",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-pgvector",
+    "version": "4.19.0-SNAPSHOT"
+  }
+}
+
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-rag
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-rag
new file mode 100644
index 000000000000..8ddcd235af2a
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-rag
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.pgvector.transform.PgVectorReverseEmbeddingsDataTypeTransformer
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-rag.json
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-rag.json
new file mode 100644
index 000000000000..bde0480f5720
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/transformer/pgvector-rag.json
@@ -0,0 +1,14 @@
+{
+  "transformer": {
+    "kind": "transformer",
+    "name": "pgvector:rag",
+    "title": "Pgvector (Rag)",
+    "description": "Prepares the PgVector similarity search results to become 
a List of String for LangChain4j RAG",
+    "deprecated": false,
+    "javaType": 
"org.apache.camel.component.pgvector.transform.PgVectorReverseEmbeddingsDataTypeTransformer",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-pgvector",
+    "version": "4.19.0-SNAPSHOT"
+  }
+}
+
diff --git 
a/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/urifactory/pgvector-endpoint
 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/urifactory/pgvector-endpoint
new file mode 100644
index 000000000000..a9f8e7a6c555
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/services/org/apache/camel/urifactory/pgvector-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.pgvector.PgVectorEndpointUriFactory
diff --git 
a/components/camel-ai/camel-pgvector/src/main/docs/pgvector-component.adoc 
b/components/camel-ai/camel-pgvector/src/main/docs/pgvector-component.adoc
new file mode 100644
index 000000000000..6d2dca26aa99
--- /dev/null
+++ b/components/camel-ai/camel-pgvector/src/main/docs/pgvector-component.adoc
@@ -0,0 +1,60 @@
+= PGVector Component
+:doctitle: PGVector
+:shortname: pgvector
+:artifactid: camel-pgvector
+:description: Perform operations on the PostgreSQL pgvector Vector Database.
+:since: 4.19
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only producer is supported
+//Manually maintained attributes
+:group: AI
+:camel-spring-boot-name: pgvector
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The PGVector Component provides support for interacting with 
https://github.com/pgvector/pgvector[pgvector],
+the open-source vector similarity search extension for PostgreSQL.
+
+== URI format
+
+----
+pgvector:collection[?options]
+----
+
+Where *collection* represents the table name used to store vectors in the 
PostgreSQL database.
+
+== Configuring the DataSource
+
+A `javax.sql.DataSource` must be provided. It is recommended to use a 
connection pooling DataSource
+(such as HikariCP) for production deployments. The DataSource can be set on 
the component or endpoint
+configuration, or autowired from the registry.
+
+== Actions
+
+The following actions are supported via the `CamelPgVectorAction` header:
+
+- `CREATE_TABLE` - Creates the pgvector extension and a table with columns: 
id, text_content, metadata, embedding
+- `DROP_TABLE` - Drops the table
+- `UPSERT` - Inserts or updates a vector record. The body must be a 
`List<Float>`. Set `CamelPgVectorRecordId` for the ID (auto-generated UUID if 
not set), `CamelPgVectorTextContent` for text, and `CamelPgVectorMetadata` for 
metadata
+- `DELETE` - Deletes a record by `CamelPgVectorRecordId`
+- `SIMILARITY_SEARCH` - Searches for similar vectors. The body must be a 
`List<Float>` query vector. Set `CamelPgVectorQueryTopK` for max results 
(default 3). Returns a `List<Map<String, Object>>` with keys: id, text_content, 
metadata, distance
+
+== LangChain4j Integration
+
+This component provides data type transformers for LangChain4j integration:
+
+- `pgvector:embeddings` - Transforms LangChain4j embedding output into a 
format suitable for the PGVector UPSERT action
+- `pgvector:rag` - Transforms similarity search results into a `List<String>` 
for RAG pipelines
+
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+include::partial$component-endpoint-headers.adoc[]
+// component options: END
+
+
+include::spring-boot:partial$starter.adoc[]
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVector.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVector.java
new file mode 100644
index 000000000000..0024a9375b6a
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVector.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector;
+
+public class PgVector {
+    public static final String SCHEME = "pgvector";
+
+    private PgVector() {
+    }
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorAction.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorAction.java
new file mode 100644
index 000000000000..1a647a4bc7a1
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorAction.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector;
+
+public enum PgVectorAction {
+    CREATE_TABLE,
+    DROP_TABLE,
+    UPSERT,
+    DELETE,
+    SIMILARITY_SEARCH
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorComponent.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorComponent.java
new file mode 100644
index 000000000000..363050f9d4ca
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorComponent.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+
+@Component(PgVector.SCHEME)
+public class PgVectorComponent extends DefaultComponent {
+
+    @Metadata
+    private PgVectorConfiguration configuration;
+
+    public PgVectorComponent() {
+        this(null);
+    }
+
+    public PgVectorComponent(CamelContext context) {
+        super(context);
+
+        this.configuration = new PgVectorConfiguration();
+    }
+
+    public PgVectorConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    /**
+     * The configuration;
+     */
+    public void setConfiguration(PgVectorConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    protected Endpoint createEndpoint(
+            String uri,
+            String remaining,
+            Map<String, Object> parameters)
+            throws Exception {
+
+        PgVectorConfiguration configuration = this.configuration.copy();
+
+        PgVectorEndpoint endpoint = new PgVectorEndpoint(uri, this, remaining, 
configuration);
+        setProperties(endpoint, parameters);
+
+        return endpoint;
+    }
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorConfiguration.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorConfiguration.java
new file mode 100644
index 000000000000..e61e1849f097
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorConfiguration.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector;
+
+import java.util.Set;
+
+import javax.sql.DataSource;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+
+@Configurer
+@UriParams
+public class PgVectorConfiguration implements Cloneable {
+
+    private static final Set<String> VALID_DISTANCE_TYPES = Set.of("cosine", 
"euclidean", "innerProduct");
+
+    @Metadata(autowired = true,
+              description = "The DataSource to use for connecting to the 
PostgreSQL database with pgvector extension.")
+    @UriParam
+    private DataSource dataSource;
+
+    @Metadata(label = "producer",
+              description = "The dimension of the vectors to store.")
+    @UriParam(defaultValue = "384")
+    private int dimension = 384;
+
+    @Metadata(label = "producer",
+              description = "The distance type to use for similarity search.",
+              enums = "cosine,euclidean,innerProduct")
+    @UriParam(defaultValue = "cosine")
+    private String distanceType = "cosine";
+
+    public DataSource getDataSource() {
+        return dataSource;
+    }
+
+    /**
+     * The DataSource to use for connecting to the PostgreSQL database with 
pgvector extension.
+     */
+    public void setDataSource(DataSource dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public int getDimension() {
+        return dimension;
+    }
+
+    /**
+     * The dimension of the vectors to store.
+     */
+    public void setDimension(int dimension) {
+        this.dimension = dimension;
+    }
+
+    public String getDistanceType() {
+        return distanceType;
+    }
+
+    /**
+     * The distance type to use for similarity search. Supported values: 
cosine, euclidean, innerProduct.
+     */
+    public void setDistanceType(String distanceType) {
+        if (!VALID_DISTANCE_TYPES.contains(distanceType)) {
+            throw new IllegalArgumentException(
+                    "Invalid distanceType: " + distanceType + ". Valid values 
are: " + VALID_DISTANCE_TYPES);
+        }
+        this.distanceType = distanceType;
+    }
+
+    // ************************
+    //
+    // Clone
+    //
+    // ************************
+    public PgVectorConfiguration copy() {
+        try {
+            return (PgVectorConfiguration) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorEndpoint.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorEndpoint.java
new file mode 100644
index 000000000000..a22f811cd0cb
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorEndpoint.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector;
+
+import javax.sql.DataSource;
+
+import org.apache.camel.Category;
+import org.apache.camel.Component;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.support.DefaultEndpoint;
+
+/**
+ * Perform operations on the PostgreSQL pgvector Vector Database.
+ */
+@UriEndpoint(
+             firstVersion = "4.19.0",
+             scheme = PgVector.SCHEME,
+             title = "PGVector",
+             syntax = "pgvector:collection",
+             producerOnly = true,
+             category = {
+                     Category.DATABASE,
+                     Category.AI
+             },
+             headersClass = PgVectorHeaders.class)
+public class PgVectorEndpoint extends DefaultEndpoint {
+
+    @Metadata(required = true)
+    @UriPath(description = "The collection (table) name")
+    private final String collection;
+
+    @UriParam
+    private PgVectorConfiguration configuration;
+
+    public PgVectorEndpoint(
+                            String endpointUri,
+                            Component component,
+                            String collection,
+                            PgVectorConfiguration configuration) {
+
+        super(endpointUri, component);
+
+        this.collection = collection;
+        this.configuration = configuration;
+    }
+
+    public PgVectorConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public String getCollection() {
+        return collection;
+    }
+
+    public DataSource getDataSource() {
+        return this.configuration.getDataSource();
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        return new PgVectorProducer(this);
+    }
+
+    @Override
+    public Consumer createConsumer(Processor processor) throws Exception {
+        throw new UnsupportedOperationException("Consumer is not implemented 
for this component");
+    }
+
+    @Override
+    public void doStart() throws Exception {
+        super.doStart();
+
+        if (configuration.getDataSource() == null) {
+            throw new IllegalArgumentException("DataSource must be configured 
on the pgvector component or endpoint");
+        }
+    }
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorHeaders.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorHeaders.java
new file mode 100644
index 000000000000..eb80eec3fc07
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorHeaders.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector;
+
+import org.apache.camel.spi.Metadata;
+
+public class PgVectorHeaders {
+
+    @Metadata(description = "The action to be performed.",
+              javaType = "String",
+              enums = 
"CREATE_TABLE,DROP_TABLE,UPSERT,DELETE,SIMILARITY_SEARCH")
+    public static final String ACTION = "CamelPgVectorAction";
+
+    @Metadata(description = "The id of the vector record.",
+              javaType = "String")
+    public static final String RECORD_ID = "CamelPgVectorRecordId";
+
+    @Metadata(description = "The maximum number of results to return for 
similarity search.",
+              javaType = "Integer", defaultValue = "3")
+    public static final String QUERY_TOP_K = "CamelPgVectorQueryTopK";
+
+    @Metadata(description = "The text content to store alongside the vector 
embedding.",
+              javaType = "String")
+    public static final String TEXT_CONTENT = "CamelPgVectorTextContent";
+
+    @Metadata(description = "The metadata associated with the vector record, 
stored as JSON.",
+              javaType = "String")
+    public static final String METADATA = "CamelPgVectorMetadata";
+
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorProducer.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorProducer.java
new file mode 100644
index 000000000000..02447160f59c
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/PgVectorProducer.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.pgvector.PGvector;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.NoSuchHeaderException;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.support.ExchangeHelper;
+
+public class PgVectorProducer extends DefaultProducer {
+
+    public PgVectorProducer(PgVectorEndpoint endpoint) {
+        super(endpoint);
+    }
+
+    @Override
+    public PgVectorEndpoint getEndpoint() {
+        return (PgVectorEndpoint) super.getEndpoint();
+    }
+
+    @Override
+    public void process(Exchange exchange) {
+        final Message in = exchange.getMessage();
+        final PgVectorAction action = in.getHeader(PgVectorHeaders.ACTION, 
PgVectorAction.class);
+
+        try {
+            if (action == null) {
+                throw new NoSuchHeaderException("The action is a required 
header", exchange, PgVectorHeaders.ACTION);
+            }
+
+            switch (action) {
+                case CREATE_TABLE:
+                    createTable(exchange);
+                    break;
+                case DROP_TABLE:
+                    dropTable(exchange);
+                    break;
+                case UPSERT:
+                    upsert(exchange);
+                    break;
+                case DELETE:
+                    delete(exchange);
+                    break;
+                case SIMILARITY_SEARCH:
+                    similaritySearch(exchange);
+                    break;
+                default:
+                    throw new UnsupportedOperationException("Unsupported 
action: " + action.name());
+            }
+        } catch (Exception e) {
+            exchange.setException(e);
+        }
+    }
+
+    // ***************************************
+    //
+    // Actions
+    //
+    // ***************************************
+
+    private void createTable(Exchange exchange) throws SQLException {
+        String tableName = getEndpoint().getCollection();
+        int dimension = getEndpoint().getConfiguration().getDimension();
+
+        try (Connection conn = getEndpoint().getDataSource().getConnection()) {
+            try (Statement stmt = conn.createStatement()) {
+                stmt.executeUpdate("CREATE EXTENSION IF NOT EXISTS vector");
+            }
+
+            String sql = String.format(
+                    "CREATE TABLE IF NOT EXISTS %s ("
+                                       + "id VARCHAR(36) PRIMARY KEY, "
+                                       + "text_content TEXT, "
+                                       + "metadata TEXT, "
+                                       + "embedding vector(%d))",
+                    sanitizeIdentifier(tableName), dimension);
+            try (Statement stmt = conn.createStatement()) {
+                stmt.executeUpdate(sql);
+            }
+
+            exchange.getMessage().setBody(true);
+        }
+    }
+
+    private void dropTable(Exchange exchange) throws SQLException {
+        String tableName = getEndpoint().getCollection();
+
+        try (Connection conn = getEndpoint().getDataSource().getConnection()) {
+            String sql = String.format("DROP TABLE IF EXISTS %s", 
sanitizeIdentifier(tableName));
+            try (Statement stmt = conn.createStatement()) {
+                stmt.executeUpdate(sql);
+            }
+
+            exchange.getMessage().setBody(true);
+        }
+    }
+
+    private void upsert(Exchange exchange) throws Exception {
+        final Message in = exchange.getMessage();
+        String tableName = getEndpoint().getCollection();
+        String id = in.getHeader(PgVectorHeaders.RECORD_ID, () -> 
UUID.randomUUID().toString(), String.class);
+
+        List<Float> vector = in.getMandatoryBody(List.class);
+        float[] vectorArray = toFloatArray(vector);
+
+        String textContent = in.getHeader(PgVectorHeaders.TEXT_CONTENT, 
String.class);
+        String metadata = in.getHeader(PgVectorHeaders.METADATA, String.class);
+
+        String sql = String.format(
+                "INSERT INTO %s (id, text_content, metadata, embedding) VALUES 
(?, ?, ?, ?) "
+                                   + "ON CONFLICT (id) DO UPDATE SET 
text_content = EXCLUDED.text_content, "
+                                   + "metadata = EXCLUDED.metadata, embedding 
= EXCLUDED.embedding",
+                sanitizeIdentifier(tableName));
+
+        try (Connection conn = getEndpoint().getDataSource().getConnection()) {
+            PGvector.addVectorType(conn);
+            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
+                pstmt.setString(1, id);
+                pstmt.setString(2, textContent);
+                pstmt.setString(3, metadata);
+                pstmt.setObject(4, new PGvector(vectorArray));
+                pstmt.executeUpdate();
+            }
+        }
+
+        exchange.getMessage().setBody(id);
+    }
+
+    private void delete(Exchange exchange) throws Exception {
+        String tableName = getEndpoint().getCollection();
+        String id = ExchangeHelper.getMandatoryHeader(exchange, 
PgVectorHeaders.RECORD_ID, String.class);
+
+        String sql = String.format("DELETE FROM %s WHERE id = ?", 
sanitizeIdentifier(tableName));
+
+        try (Connection conn = getEndpoint().getDataSource().getConnection()) {
+            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
+                pstmt.setString(1, id);
+                int deleted = pstmt.executeUpdate();
+                exchange.getMessage().setBody(deleted > 0);
+            }
+        }
+    }
+
+    private void similaritySearch(Exchange exchange) throws Exception {
+        final Message in = exchange.getMessage();
+        String tableName = getEndpoint().getCollection();
+        int topK = in.getHeader(PgVectorHeaders.QUERY_TOP_K, 3, Integer.class);
+        String distanceType = 
getEndpoint().getConfiguration().getDistanceType();
+
+        List<Float> queryVector = in.getMandatoryBody(List.class);
+        float[] vectorArray = toFloatArray(queryVector);
+
+        String distanceOp = getDistanceOperator(distanceType);
+        String sql = String.format(
+                "SELECT id, text_content, metadata, embedding %s ? AS distance 
FROM %s ORDER BY embedding %s ? LIMIT ?",
+                distanceOp, sanitizeIdentifier(tableName), distanceOp);
+
+        try (Connection conn = getEndpoint().getDataSource().getConnection()) {
+            PGvector.addVectorType(conn);
+            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
+                PGvector pgVector = new PGvector(vectorArray);
+                pstmt.setObject(1, pgVector);
+                pstmt.setObject(2, pgVector);
+                pstmt.setInt(3, topK);
+
+                try (ResultSet rs = pstmt.executeQuery()) {
+                    List<Map<String, Object>> results = new ArrayList<>();
+                    while (rs.next()) {
+                        Map<String, Object> row = new HashMap<>();
+                        row.put("id", rs.getString("id"));
+                        row.put("text_content", rs.getString("text_content"));
+                        row.put("metadata", rs.getString("metadata"));
+                        row.put("distance", rs.getDouble("distance"));
+                        results.add(row);
+                    }
+                    exchange.getMessage().setBody(results);
+                }
+            }
+        }
+    }
+
+    // ***************************************
+    //
+    // Helpers
+    //
+    // ***************************************
+
+    private static float[] toFloatArray(List<Float> vector) {
+        float[] result = new float[vector.size()];
+        for (int i = 0; i < vector.size(); i++) {
+            result[i] = vector.get(i);
+        }
+        return result;
+    }
+
+    private static String getDistanceOperator(String distanceType) {
+        return switch (distanceType) {
+            case "euclidean" -> "<->";
+            case "innerProduct" -> "<#>";
+            case "cosine" -> "<=>";
+            default -> throw new IllegalArgumentException("Unknown distance 
type: " + distanceType);
+        };
+    }
+
+    private static String sanitizeIdentifier(String identifier) {
+        if (!identifier.matches("[a-zA-Z_][a-zA-Z0-9_]*")) {
+            throw new IllegalArgumentException("Invalid SQL identifier: " + 
identifier);
+        }
+        return identifier;
+    }
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/transform/PgVectorEmbeddingsDataTypeTransformer.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/transform/PgVectorEmbeddingsDataTypeTransformer.java
new file mode 100644
index 000000000000..166d8c64f958
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/transform/PgVectorEmbeddingsDataTypeTransformer.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector.transform;
+
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import dev.langchain4j.data.document.Metadata;
+import dev.langchain4j.data.embedding.Embedding;
+import dev.langchain4j.data.segment.TextSegment;
+import org.apache.camel.Message;
+import org.apache.camel.ai.CamelLangchain4jAttributes;
+import org.apache.camel.component.pgvector.PgVectorHeaders;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.spi.DataTypeTransformer;
+import org.apache.camel.spi.Transformer;
+
+/**
+ * Maps a LangChain4j Embeddings to a PgVector upsert message to write an 
embeddings vector on a PostgreSQL pgvector
+ * database.
+ */
+@DataTypeTransformer(name = "pgvector:embeddings",
+                     description = "Prepares the message to become an object 
writable by PgVector component")
+public class PgVectorEmbeddingsDataTypeTransformer extends Transformer {
+
+    @Override
+    public void transform(Message message, DataType fromType, DataType toType) 
{
+        Embedding embedding
+                = 
message.getHeader(CamelLangchain4jAttributes.CAMEL_LANGCHAIN4J_EMBEDDING_VECTOR,
 Embedding.class);
+        TextSegment text = message.getBody(TextSegment.class);
+
+        String id = message.getHeader(PgVectorHeaders.RECORD_ID, () -> 
UUID.randomUUID().toString(), String.class);
+        message.setHeader(PgVectorHeaders.RECORD_ID, id);
+
+        message.setBody(embedding.vectorAsList());
+
+        if (text != null) {
+            message.setHeader(PgVectorHeaders.TEXT_CONTENT, text.text());
+            Metadata metadata = text.metadata();
+            if (metadata != null && !metadata.toMap().isEmpty()) {
+                message.setHeader(PgVectorHeaders.METADATA, 
toJson(metadata.toMap()));
+            }
+        }
+    }
+
+    private static String toJson(Map<String, Object> map) {
+        return "{" + map.entrySet().stream()
+                .map(e -> "\"" + escapeJson(String.valueOf(e.getKey())) + 
"\":\""
+                          + escapeJson(String.valueOf(e.getValue())) + "\"")
+                .collect(Collectors.joining(","))
+               + "}";
+    }
+
+    private static String escapeJson(String value) {
+        return value.replace("\\", "\\\\")
+                .replace("\"", "\\\"")
+                .replace("\n", "\\n")
+                .replace("\r", "\\r")
+                .replace("\t", "\\t");
+    }
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/transform/PgVectorReverseEmbeddingsDataTypeTransformer.java
 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/transform/PgVectorReverseEmbeddingsDataTypeTransformer.java
new file mode 100644
index 000000000000..593b8f0f0c8a
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/main/java/org/apache/camel/component/pgvector/transform/PgVectorReverseEmbeddingsDataTypeTransformer.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector.transform;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.camel.Message;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.spi.DataTypeTransformer;
+import org.apache.camel.spi.Transformer;
+
+/**
+ * Maps a List of PgVector similarity search results to a List of String for 
LangChain4j RAG.
+ */
+@DataTypeTransformer(name = "pgvector:rag",
+                     description = "Prepares the PgVector similarity search 
results to become a List of String for LangChain4j RAG")
+public class PgVectorReverseEmbeddingsDataTypeTransformer extends Transformer {
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void transform(Message message, DataType from, DataType to) throws 
Exception {
+        List<Map<String, Object>> results = message.getBody(List.class);
+
+        List<String> textContents = results.stream()
+                .map(row -> (String) row.getOrDefault("text_content", ""))
+                .collect(Collectors.toList());
+
+        message.setBody(textContents);
+    }
+}
diff --git 
a/components/camel-ai/camel-pgvector/src/test/java/org/apache/camel/component/pgvector/PgVectorComponentIT.java
 
b/components/camel-ai/camel-pgvector/src/test/java/org/apache/camel/component/pgvector/PgVectorComponentIT.java
new file mode 100644
index 000000000000..a157875e5fe3
--- /dev/null
+++ 
b/components/camel-ai/camel-pgvector/src/test/java/org/apache/camel/component/pgvector/PgVectorComponentIT.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.pgvector;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.infra.postgres.services.PostgresService;
+import 
org.apache.camel.test.infra.postgres.services.PostgresVectorServiceFactory;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.postgresql.ds.PGSimpleDataSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class PgVectorComponentIT extends CamelTestSupport {
+
+    public static final String PGVECTOR_URI = "pgvector:test_embeddings";
+    private static final int DIMENSION = 3;
+
+    @RegisterExtension
+    static PostgresService POSTGRES = 
PostgresVectorServiceFactory.createService();
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+
+        PGSimpleDataSource dataSource = new PGSimpleDataSource();
+        dataSource.setUrl(POSTGRES.jdbcUrl());
+        dataSource.setUser(POSTGRES.userName());
+        dataSource.setPassword(POSTGRES.password());
+
+        PgVectorComponent component = context.getComponent(PgVector.SCHEME, 
PgVectorComponent.class);
+        component.getConfiguration().setDataSource(dataSource);
+        component.getConfiguration().setDimension(DIMENSION);
+
+        return context;
+    }
+
+    @Test
+    @Order(1)
+    public void createTable() {
+        Exchange result = fluentTemplate.to(PGVECTOR_URI)
+                .withHeader(PgVectorHeaders.ACTION, 
PgVectorAction.CREATE_TABLE)
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+        assertThat(result.getMessage().getBody(Boolean.class)).isTrue();
+    }
+
+    @Test
+    @Order(2)
+    public void upsert() {
+        List<Float> vector = Arrays.asList(0.1f, 0.2f, 0.3f);
+
+        Exchange result = fluentTemplate.to(PGVECTOR_URI)
+                .withHeader(PgVectorHeaders.ACTION, PgVectorAction.UPSERT)
+                .withHeader(PgVectorHeaders.RECORD_ID, "test-1")
+                .withHeader(PgVectorHeaders.TEXT_CONTENT, "Hello World")
+                .withHeader(PgVectorHeaders.METADATA, "source=test")
+                .withBody(vector)
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+        
assertThat(result.getMessage().getBody(String.class)).isEqualTo("test-1");
+    }
+
+    @Test
+    @Order(3)
+    public void upsertSecond() {
+        List<Float> vector = Arrays.asList(0.4f, 0.5f, 0.6f);
+
+        Exchange result = fluentTemplate.to(PGVECTOR_URI)
+                .withHeader(PgVectorHeaders.ACTION, PgVectorAction.UPSERT)
+                .withHeader(PgVectorHeaders.RECORD_ID, "test-2")
+                .withHeader(PgVectorHeaders.TEXT_CONTENT, "Goodbye World")
+                .withBody(vector)
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+        
assertThat(result.getMessage().getBody(String.class)).isEqualTo("test-2");
+    }
+
+    @Test
+    @Order(4)
+    @SuppressWarnings("unchecked")
+    public void similaritySearch() {
+        List<Float> queryVector = Arrays.asList(0.1f, 0.2f, 0.3f);
+
+        Exchange result = fluentTemplate.to(PGVECTOR_URI)
+                .withHeader(PgVectorHeaders.ACTION, 
PgVectorAction.SIMILARITY_SEARCH)
+                .withHeader(PgVectorHeaders.QUERY_TOP_K, 2)
+                .withBody(queryVector)
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+
+        List<Map<String, Object>> results = 
result.getMessage().getBody(List.class);
+        assertThat(results).isNotEmpty();
+        assertThat(results).hasSizeLessThanOrEqualTo(2);
+
+        // The closest vector should be test-1 (exact match)
+        assertThat(results.get(0).get("id")).isEqualTo("test-1");
+        assertThat(results.get(0).get("text_content")).isEqualTo("Hello 
World");
+    }
+
+    @Test
+    @Order(5)
+    public void delete() {
+        Exchange result = fluentTemplate.to(PGVECTOR_URI)
+                .withHeader(PgVectorHeaders.ACTION, PgVectorAction.DELETE)
+                .withHeader(PgVectorHeaders.RECORD_ID, "test-1")
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+        assertThat(result.getMessage().getBody(Boolean.class)).isTrue();
+    }
+
+    @Test
+    @Order(6)
+    @SuppressWarnings("unchecked")
+    public void searchAfterDelete() {
+        List<Float> queryVector = Arrays.asList(0.1f, 0.2f, 0.3f);
+
+        Exchange result = fluentTemplate.to(PGVECTOR_URI)
+                .withHeader(PgVectorHeaders.ACTION, 
PgVectorAction.SIMILARITY_SEARCH)
+                .withHeader(PgVectorHeaders.QUERY_TOP_K, 2)
+                .withBody(queryVector)
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+
+        List<Map<String, Object>> results = 
result.getMessage().getBody(List.class);
+        assertThat(results).hasSize(1);
+        assertThat(results.get(0).get("id")).isEqualTo("test-2");
+    }
+
+    @Test
+    @Order(7)
+    public void dropTable() {
+        Exchange result = fluentTemplate.to(PGVECTOR_URI)
+                .withHeader(PgVectorHeaders.ACTION, PgVectorAction.DROP_TABLE)
+                .request(Exchange.class);
+
+        assertThat(result).isNotNull();
+        assertThat(result.getException()).isNull();
+        assertThat(result.getMessage().getBody(Boolean.class)).isTrue();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:in")
+                        .to(PGVECTOR_URI);
+            }
+        };
+    }
+}
diff --git a/components/camel-ai/pom.xml b/components/camel-ai/pom.xml
index b3cc35116113..d0d2ed952d81 100644
--- a/components/camel-ai/pom.xml
+++ b/components/camel-ai/pom.xml
@@ -52,6 +52,7 @@
         <module>camel-milvus</module>
         <module>camel-neo4j</module>
         <module>camel-openai</module>
+        <module>camel-pgvector</module>
         <module>camel-pinecone</module>
         <module>camel-qdrant</module>
         <module>camel-tensorflow-serving</module>
diff --git a/parent/pom.xml b/parent/pom.xml
index 73fe2178b18e..fc8e4583a315 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -458,6 +458,7 @@
         <pdfbox-version>3.0.7</pdfbox-version>
         <pgjdbc-driver-version>42.7.10</pgjdbc-driver-version>
         <pgjdbc-ng-driver-version>0.8.9</pgjdbc-ng-driver-version>
+        <pgvector-version>0.1.6</pgvector-version>
         <picocli-version>4.7.7</picocli-version>
         <pinecone-client-version>3.1.0</pinecone-client-version>
         <plc4x-version>0.13.1</plc4x-version>
@@ -2373,6 +2374,11 @@
                 <artifactId>camel-pgevent</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-pgvector</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-pinecone</artifactId>
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java
index c4ebaa99c5c3..2a51e647d6fb 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/MojoHelper.java
@@ -46,7 +46,7 @@ public final class MojoHelper {
                         dir.resolve("camel-langchain4j-web-search"),
                         dir.resolve("camel-qdrant"), 
dir.resolve("camel-milvus"), dir.resolve("camel-neo4j"),
                         dir.resolve("camel-openai"),
-                        dir.resolve("camel-pinecone"), 
dir.resolve("camel-kserve"),
+                        dir.resolve("camel-pgvector"), 
dir.resolve("camel-pinecone"), dir.resolve("camel-kserve"),
                         dir.resolve("camel-tensorflow-serving"),
                         dir.resolve("camel-weaviate"), 
dir.resolve("camel-docling"));
             case "camel-as2":


Reply via email to