diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index 4b93de1f546a1..e8668d2059c56 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -1902,6 +1902,11 @@
camel-pgevent
4.19.0-SNAPSHOT
+
+ org.apache.camel
+ camel-pgvector
+ 4.19.0-SNAPSHOT
+
org.apache.camel
camel-pinecone
diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml
index 593117e20b1c2..ea92025722c8e 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -1692,6 +1692,11 @@
camel-pgevent
${project.version}
+
+ org.apache.camel
+ camel-pgvector
+ ${project.version}
+
org.apache.camel
camel-pinecone
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
index e9742912148af..6d730df36b5ac 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
@@ -295,6 +295,7 @@ paho-mqtt5
pdf
pg-replication-slot
pgevent
+pgvector
pinecone
platform-http
plc4x
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pgvector.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pgvector.json
new file mode 100644
index 0000000000000..163451d430669
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pgvector.json
@@ -0,0 +1,50 @@
+{
+ "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": "enum", "javaType": "org.apache.camel.component.pgvector.PgVectorDistanceType", "enum": [ "COSINE", "EUCLIDEAN", "INNER_PRODUCT" ], "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 during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
+ "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 type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }
+ },
+ "headers": {
+ "CamelPgVectorAction": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "enum": [ "CREATE_TABLE", "CREATE_INDEX", "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" },
+ "CamelPgVectorFilter": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Filter condition for similarity search. Applied as a SQL WHERE clause on the text_content and metadata columns. Supports parameterized queries using placeholders with values provided via the CamelPgVectorFilterParams header. WARNING: When not using parameterized queries, the filter value is appended directly as SQL. Never use untrusted input as the filter value without parameterization, as this could lead to SQL injection.", "constantName": "org.apache.camel.component.pgvector.PgVectorHeaders#FILTER" },
+ "CamelPgVectorFilterParams": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.List", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Parameter values for parameterized filter queries. Use with placeholders in the CamelPgVectorFilter header. Example: filter = 'text_content LIKE AND metadata::jsonb-'category' = ' with filterParams = List.of(%hello%, science).", "constantName": "org.apache.camel.component.pgvector.PgVectorHeaders#FILTER_PARAMS" }
+ },
+ "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 extension." },
+ "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": "enum", "javaType": "org.apache.camel.component.pgvector.PgVectorDistanceType", "enum": [ "COSINE", "EUCLIDEAN", "INNER_PRODUCT" ], "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }
+ }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
index c261164480cc8..51e76f50317c1 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
@@ -32,6 +32,8 @@ infinispan-embeddings
milvus-embeddings
neo4j-embeddings
neo4j-rag
+pgvector-embeddings
+pgvector-rag
pinecone-embeddings
pinecone-rag
protobuf-binary
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/pgvector-embeddings.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/pgvector-embeddings.json
new file mode 100644
index 0000000000000..2a5efd26fd33d
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/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/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/pgvector-rag.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/pgvector-rag.json
new file mode 100644
index 0000000000000..bde0480f57203
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/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-langchain4j-embeddings/pom.xml b/components/camel-ai/camel-langchain4j-embeddings/pom.xml
index 9ea004fe94ca0..9993ff4d88259 100644
--- a/components/camel-ai/camel-langchain4j-embeddings/pom.xml
+++ b/components/camel-ai/camel-langchain4j-embeddings/pom.xml
@@ -87,6 +87,11 @@
camel-milvus
test
+
+ org.apache.camel
+ camel-pgvector
+ test
+
org.apache.camel
camel-pinecone
@@ -156,6 +161,12 @@
${project.version}
test
+
+ org.apache.camel
+ camel-test-infra-postgres
+ ${project.version}
+ test
+
org.apache.camel
camel-test-infra-weaviate
diff --git a/components/camel-ai/camel-langchain4j-embeddings/src/main/docs/langchain4j-embeddings-component.adoc b/components/camel-ai/camel-langchain4j-embeddings/src/main/docs/langchain4j-embeddings-component.adoc
index b9328f28701d4..884940a9dc067 100644
--- a/components/camel-ai/camel-langchain4j-embeddings/src/main/docs/langchain4j-embeddings-component.adoc
+++ b/components/camel-ai/camel-langchain4j-embeddings/src/main/docs/langchain4j-embeddings-component.adoc
@@ -268,6 +268,77 @@ YAML::
----
====
+==== Using with PGVector
+
+This example shows how to embed text and store it in PostgreSQL with pgvector:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:store")
+ .to("langchain4j-embeddings:embed")
+ .setHeader(PgVectorHeaders.ACTION).constant(PgVectorAction.UPSERT)
+ .transformDataType(new DataType("pgvector:embeddings"))
+ .to("pgvector:myCollection");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: "direct:store"
+ steps:
+ - to: "langchain4j-embeddings:embed"
+ - setHeader:
+ name: CamelPgVectorAction
+ constant: UPSERT
+ - transform:
+ dataType: "pgvector:embeddings"
+ - to: "pgvector:myCollection"
+----
+====
+
+Similarity search with PGVector and RAG:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:search")
+ .to("langchain4j-embeddings:embed")
+ .transformDataType(new DataType("pgvector:embeddings"))
+ .setHeader(PgVectorHeaders.ACTION, constant(PgVectorAction.SIMILARITY_SEARCH))
+ .to("pgvector:myCollection")
+ .transformDataType(new DataType("pgvector:rag"));
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: "direct:search"
+ steps:
+ - to: "langchain4j-embeddings:embed"
+ - transform:
+ dataType: "pgvector:embeddings"
+ - setHeader:
+ name: CamelPgVectorAction
+ constant: SIMILARITY_SEARCH
+ - to: "pgvector:myCollection"
+ - transform:
+ dataType: "pgvector:rag"
+----
+====
+
==== Using with LangChain4j Embedding Store Component
For a simpler integration, use the `langchain4j-embeddingstore` component which provides a unified interface:
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 0000000000000..cb1f75b825ef8
--- /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 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-openai/src/main/docs/openai-component.adoc b/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc
index 4e09e1d24eccb..484534bd3f432 100644
--- a/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc
+++ b/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc
@@ -420,6 +420,8 @@ For single-input requests, the component returns a raw `List` embedding v
==== PostgreSQL + pgvector (Recommended)
+Using the xref:pgvector-component.adoc[PGVector] component:
+
[source,yaml]
----
# Index documents in PostgreSQL with pgvector
@@ -434,11 +436,42 @@ For single-input requests, the component returns a raw `List` embedding v
uri: openai:embeddings
parameters:
embeddingModel: nomic-embed-text
- - setVariable:
- name: embedding
- simple: "${body.toString()}"
+ - setHeader:
+ name: CamelPgVectorAction
+ constant: UPSERT
+ - setHeader:
+ name: CamelPgVectorTextContent
+ simple: "${variable.text}"
+ - to:
+ uri: pgvector:documents
+
+# Similarity search
+- route:
+ from:
+ uri: direct:search
+ steps:
+ - to:
+ uri: openai:embeddings
+ parameters:
+ embeddingModel: nomic-embed-text
+ - setHeader:
+ name: CamelPgVectorAction
+ constant: SIMILARITY_SEARCH
+ - setHeader:
+ name: CamelPgVectorQueryTopK
+ constant: 5
- to:
- uri: sql:INSERT INTO documents (content, embedding) VALUES (:#text, :#embedding::vector)
+ uri: pgvector:documents
+----
+
+The pgvector component handles table creation, HNSW indexing, upsert with conflict resolution, and similarity search with configurable distance types (cosine, euclidean, inner product). See the xref:pgvector-component.adoc[PGVector component documentation] for details.
+
+For custom table schemas, complex queries (joins, CTEs), or integration with existing PostgreSQL tables, you can use `camel-sql` directly with the pgvector extension:
+
+[source,yaml]
+----
+- to:
+ uri: sql:INSERT INTO documents (content, embedding) VALUES (:#text, :#embedding::vector)
----
==== Alternative: Dedicated Vector Databases
diff --git a/components/camel-ai/camel-pgvector/pom.xml b/components/camel-ai/camel-pgvector/pom.xml
new file mode 100644
index 0000000000000..b02e9208d361a
--- /dev/null
+++ b/components/camel-ai/camel-pgvector/pom.xml
@@ -0,0 +1,90 @@
+
+
+
+ 4.0.0
+
+
+ camel-ai-parent
+ org.apache.camel
+ 4.19.0-SNAPSHOT
+
+
+ camel-pgvector
+ jar
+ Camel :: AI :: PGVector
+ Camel PGVector support
+
+
+ true
+ 4
+
+
+
+
+ org.apache.camel
+ camel-support
+
+
+
+ dev.langchain4j
+ langchain4j-core
+ ${langchain4j-version}
+
+
+
+ org.postgresql
+ postgresql
+ ${pgjdbc-driver-version}
+
+
+
+ com.pgvector
+ pgvector
+ ${pgvector-version}
+
+
+
+
+ org.apache.camel
+ camel-test-infra-postgres
+ ${project.version}
+ test
+
+
+
+
+ org.apache.camel
+ camel-test-junit6
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+
+
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 0000000000000..49501a70110a5
--- /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, org.apache.camel.component.pgvector.PgVectorDistanceType.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 org.apache.camel.component.pgvector.PgVectorDistanceType.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 0000000000000..48387e1f34519
--- /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, org.apache.camel.component.pgvector.PgVectorDistanceType.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 org.apache.camel.component.pgvector.PgVectorDistanceType.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 0000000000000..1e3f50746b82b
--- /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, org.apache.camel.component.pgvector.PgVectorDistanceType.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 org.apache.camel.component.pgvector.PgVectorDistanceType.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 0000000000000..c41db64d0fcbe
--- /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 PROPERTY_NAMES;
+ private static final Set SECRET_PROPERTY_NAMES;
+ private static final Map MULTI_VALUE_PREFIXES;
+ static {
+ Set 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 properties, boolean encode) throws URISyntaxException {
+ String syntax = scheme + BASE;
+ String uri = syntax;
+
+ Map copy = new HashMap<>(properties);
+
+ uri = buildPathParameter(syntax, uri, "collection", null, true, copy);
+ uri = buildQueryParameters(uri, copy, encode);
+ return uri;
+ }
+
+ @Override
+ public Set propertyNames() {
+ return PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set secretPropertyNames() {
+ return SECRET_PROPERTY_NAMES;
+ }
+
+ @Override
+ public Map 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 0000000000000..163451d430669
--- /dev/null
+++ b/components/camel-ai/camel-pgvector/src/generated/resources/META-INF/org/apache/camel/component/pgvector/pgvector.json
@@ -0,0 +1,50 @@
+{
+ "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": "enum", "javaType": "org.apache.camel.component.pgvector.PgVectorDistanceType", "enum": [ "COSINE", "EUCLIDEAN", "INNER_PRODUCT" ], "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 during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
+ "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 type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }
+ },
+ "headers": {
+ "CamelPgVectorAction": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "enum": [ "CREATE_TABLE", "CREATE_INDEX", "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" },
+ "CamelPgVectorFilter": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Filter condition for similarity search. Applied as a SQL WHERE clause on the text_content and metadata columns. Supports parameterized queries using placeholders with values provided via the CamelPgVectorFilterParams header. WARNING: When not using parameterized queries, the filter value is appended directly as SQL. Never use untrusted input as the filter value without parameterization, as this could lead to SQL injection.", "constantName": "org.apache.camel.component.pgvector.PgVectorHeaders#FILTER" },
+ "CamelPgVectorFilterParams": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.List", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Parameter values for parameterized filter queries. Use with placeholders in the CamelPgVectorFilter header. Example: filter = 'text_content LIKE AND metadata::jsonb-'category' = ' with filterParams = List.of(%hello%, science).", "constantName": "org.apache.camel.component.pgvector.PgVectorHeaders#FILTER_PARAMS" }
+ },
+ "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 extension." },
+ "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": "enum", "javaType": "org.apache.camel.component.pgvector.PgVectorDistanceType", "enum": [ "COSINE", "EUCLIDEAN", "INNER_PRODUCT" ], "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 producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }
+ }
+}
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 0000000000000..cad7e0ed66910
--- /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 0000000000000..3945951638c5b
--- /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 0000000000000..cf12de7c025d5
--- /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 0000000000000..fd431f002970f
--- /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 0000000000000..483f077e2040f
--- /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 0000000000000..27a4f45b1c785
--- /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 0000000000000..4b6963457fb08
--- /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 0000000000000..2a5efd26fd33d
--- /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 0000000000000..8ddcd235af2a5
--- /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 0000000000000..bde0480f57203
--- /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 0000000000000..a9f8e7a6c555d
--- /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 0000000000000..6048cd9f37fc5
--- /dev/null
+++ b/components/camel-ai/camel-pgvector/src/main/docs/pgvector-component.adoc
@@ -0,0 +1,206 @@
+= 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
+
+*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
+- `CREATE_INDEX` - Creates an HNSW index on the embedding column for faster approximate nearest neighbor search. The index uses the distance type configured on the endpoint (default: COSINE)
+- `DROP_TABLE` - Drops the table
+- `UPSERT` - Inserts or updates a vector record. The body must be a `List`. 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` query vector. Set `CamelPgVectorQueryTopK` for max results (default 3). Optionally set `CamelPgVectorFilter` with a SQL WHERE clause to filter results (e.g., `text_content LIKE '%hello%'`). Returns a `List
+
+ org.apache.camel
+ camel-pgvector
+ ${project.version}
+
org.apache.camel
camel-pinecone
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 4b0a6d66e0d01..46f7670f3996f 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 static List getComponentPath(Path dir) {
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":