You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2024/03/15 11:41:40 UTC
(camel) 01/05: CAMEL-20485 - Create a Camel-Milvus component
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch milvus-component
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 1f03298b4f1f295ad99e46d9a206d5e675fe04a3
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Thu Mar 14 14:10:52 2024 +0100
CAMEL-20485 - Create a Camel-Milvus component
Signed-off-by: Andrea Cosentino <an...@gmail.com>
---
catalog/camel-allcomponents/pom.xml | 5 +
components/camel-milvus/pom.xml | 122 ++++++++++
.../milvus/MilvusComponentConfigurer.java | 77 ++++++
.../milvus/MilvusConfigurationConfigurer.java | 73 ++++++
.../component/milvus/MilvusEndpointConfigurer.java | 61 +++++
.../component/milvus/MilvusEndpointUriFactory.java | 75 ++++++
.../org/apache/camel/component/milvus/milvus.json | 53 ++++
.../services/org/apache/camel/component.properties | 7 +
.../services/org/apache/camel/component/milvus | 2 +
.../org/apache/camel/configurer/milvus-component | 2 +
.../org/apache/camel/configurer/milvus-endpoint | 2 +
...ache.camel.component.milvus.MilvusConfiguration | 2 +
.../org/apache/camel/urifactory/milvus-endpoint | 2 +
.../src/main/docs/qdrant-component.adoc | 134 ++++++++++
.../org/apache/camel/component/milvus/Milvus.java | 57 +++++
.../camel/component/milvus/MilvusAction.java | 26 ++
.../camel/component/milvus/MilvusComponent.java | 71 ++++++
.../component/milvus/MilvusConfiguration.java | 116 +++++++++
.../camel/component/milvus/MilvusEndpoint.java | 140 +++++++++++
.../camel/component/milvus/MilvusProducer.java | 192 +++++++++++++++
.../milvus/MilvusCreateCollectionTest.java | 74 ++++++
.../camel/component/milvus/MilvusTestSupport.java | 45 ++++
.../camel/component/milvus/MilvusUpsertTest.java | 42 ++++
.../component/milvus/it/MilvusComponentIT.java | 269 +++++++++++++++++++++
.../src/test/resources/log4j2.properties | 35 +++
parent/pom.xml | 5 +
test-infra/camel-test-infra-milvus/pom.xml | 55 +++++
.../src/main/resources/META-INF/MANIFEST.MF | 0
.../test/infra/milvus/common/MilvusProperties.java | 27 +++
.../services/MilvusLocalContainerService.java | 81 +++++++
.../infra/milvus/services/MilvusRemoteService.java | 42 ++++
.../test/infra/milvus/services/MilvusService.java | 27 +++
.../milvus/services/MilvusServiceFactory.java | 55 +++++
.../infra/milvus/services/container.properties | 17 ++
test-infra/pom.xml | 1 +
35 files changed, 1994 insertions(+)
diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml
index a4f3074ba0a..eea65801cb7 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -1197,6 +1197,11 @@
<artifactId>camel-microprofile-health</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-milvus</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-mina</artifactId>
diff --git a/components/camel-milvus/pom.xml b/components/camel-milvus/pom.xml
new file mode 100644
index 00000000000..7e707de0f28
--- /dev/null
+++ b/components/camel-milvus/pom.xml
@@ -0,0 +1,122 @@
+<?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>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>components</artifactId>
+ <version>4.5.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-milvus</artifactId>
+ <packaging>jar</packaging>
+ <name>Camel :: Milvus</name>
+ <description>Camel Milvus support</description>
+
+ <properties>
+ <camel.surefire.parallel>true</camel.surefire.parallel>
+ <camel.surefire.parallel.factor>4</camel.surefire.parallel.factor>
+
+ <!-- Qdrant is not available on these platforms -->
+ <skipITs.ppc64le>true</skipITs.ppc64le>
+ <skipITs.s390x>true</skipITs.s390x>
+ <skipTests.ppc64le>true</skipTests.ppc64le>
+ <skipTests.s390x>true</skipTests.s390x>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-support</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.milvus</groupId>
+ <artifactId>milvus-sdk-java</artifactId>
+ <version>2.3.4</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-direct</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-mock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-jackson</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>io.rest-assured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <version>${rest-assured-version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj-version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- test infra -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-infra-milvus</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusComponentConfigurer.java b/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusComponentConfigurer.java
new file mode 100644
index 00000000000..44c50b6fbd3
--- /dev/null
+++ b/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusComponentConfigurer.java
@@ -0,0 +1,77 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.milvus;
+
+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!
+ */
+@SuppressWarnings("unchecked")
+public class MilvusComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ private org.apache.camel.component.milvus.MilvusConfiguration getOrCreateConfiguration(MilvusComponent target) {
+ if (target.getConfiguration() == null) {
+ target.setConfiguration(new org.apache.camel.component.milvus.MilvusConfiguration());
+ }
+ return target.getConfiguration();
+ }
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ MilvusComponent target = (MilvusComponent) 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.milvus.MilvusConfiguration.class, value)); return true;
+ case "host": getOrCreateConfiguration(target).setHost(property(camelContext, java.lang.String.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "port": getOrCreateConfiguration(target).setPort(property(camelContext, int.class, value)); return true;
+ case "timeout": getOrCreateConfiguration(target).setTimeout(property(camelContext, long.class, value)); return true;
+ case "token": getOrCreateConfiguration(target).setToken(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 "autowiredenabled":
+ case "autowiredEnabled": return boolean.class;
+ case "configuration": return org.apache.camel.component.milvus.MilvusConfiguration.class;
+ case "host": return java.lang.String.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "port": return int.class;
+ case "timeout": return long.class;
+ case "token": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ MilvusComponent target = (MilvusComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return target.isAutowiredEnabled();
+ case "configuration": return target.getConfiguration();
+ case "host": return getOrCreateConfiguration(target).getHost();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "port": return getOrCreateConfiguration(target).getPort();
+ case "timeout": return getOrCreateConfiguration(target).getTimeout();
+ case "token": return getOrCreateConfiguration(target).getToken();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusConfigurationConfigurer.java b/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusConfigurationConfigurer.java
new file mode 100644
index 00000000000..1cbd71181f7
--- /dev/null
+++ b/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusConfigurationConfigurer.java
@@ -0,0 +1,73 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.milvus;
+
+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.milvus.MilvusConfiguration;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class MilvusConfigurationConfigurer 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.milvus.MilvusConfiguration target = (org.apache.camel.component.milvus.MilvusConfiguration) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "client":
+ case "Client": target.setClient(property(camelContext, io.milvus.client.MilvusClient.class, value)); return true;
+ case "host":
+ case "Host": target.setHost(property(camelContext, java.lang.String.class, value)); return true;
+ case "port":
+ case "Port": target.setPort(property(camelContext, int.class, value)); return true;
+ case "timeout":
+ case "Timeout": target.setTimeout(property(camelContext, long.class, value)); return true;
+ case "token":
+ case "Token": target.setToken(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 "client":
+ case "Client": return io.milvus.client.MilvusClient.class;
+ case "host":
+ case "Host": return java.lang.String.class;
+ case "port":
+ case "Port": return int.class;
+ case "timeout":
+ case "Timeout": return long.class;
+ case "token":
+ case "Token": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ org.apache.camel.component.milvus.MilvusConfiguration target = (org.apache.camel.component.milvus.MilvusConfiguration) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "client":
+ case "Client": return target.getClient();
+ case "host":
+ case "Host": return target.getHost();
+ case "port":
+ case "Port": return target.getPort();
+ case "timeout":
+ case "Timeout": return target.getTimeout();
+ case "token":
+ case "Token": return target.getToken();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusEndpointConfigurer.java b/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusEndpointConfigurer.java
new file mode 100644
index 00000000000..208b66c195c
--- /dev/null
+++ b/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusEndpointConfigurer.java
@@ -0,0 +1,61 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.milvus;
+
+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!
+ */
+@SuppressWarnings("unchecked")
+public class MilvusEndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ MilvusEndpoint target = (MilvusEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "host": target.getConfiguration().setHost(property(camelContext, java.lang.String.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "port": target.getConfiguration().setPort(property(camelContext, int.class, value)); return true;
+ case "timeout": target.getConfiguration().setTimeout(property(camelContext, long.class, value)); return true;
+ case "token": target.getConfiguration().setToken(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 "host": return java.lang.String.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "port": return int.class;
+ case "timeout": return long.class;
+ case "token": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ MilvusEndpoint target = (MilvusEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "host": return target.getConfiguration().getHost();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "port": return target.getConfiguration().getPort();
+ case "timeout": return target.getConfiguration().getTimeout();
+ case "token": return target.getConfiguration().getToken();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusEndpointUriFactory.java b/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusEndpointUriFactory.java
new file mode 100644
index 00000000000..bec8e537b69
--- /dev/null
+++ b/components/camel-milvus/src/generated/java/org/apache/camel/component/milvus/MilvusEndpointUriFactory.java
@@ -0,0 +1,75 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.milvus;
+
+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!
+ */
+public class MilvusEndpointUriFactory 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 Set<String> MULTI_VALUE_PREFIXES;
+ static {
+ Set<String> props = new HashSet<>(6);
+ props.add("collection");
+ props.add("host");
+ props.add("lazyStartProducer");
+ props.add("port");
+ props.add("timeout");
+ props.add("token");
+ PROPERTY_NAMES = Collections.unmodifiableSet(props);
+ Set<String> secretProps = new HashSet<>(1);
+ secretProps.add("token");
+ SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps);
+ MULTI_VALUE_PREFIXES = Collections.emptySet();
+ }
+
+ @Override
+ public boolean isEnabled(String scheme) {
+ return "milvus".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 Set<String> multiValuePrefixes() {
+ return MULTI_VALUE_PREFIXES;
+ }
+
+ @Override
+ public boolean isLenientProperties() {
+ return false;
+ }
+}
+
diff --git a/components/camel-milvus/src/generated/resources/META-INF/org/apache/camel/component/milvus/milvus.json b/components/camel-milvus/src/generated/resources/META-INF/org/apache/camel/component/milvus/milvus.json
new file mode 100644
index 00000000000..a27466d4406
--- /dev/null
+++ b/components/camel-milvus/src/generated/resources/META-INF/org/apache/camel/component/milvus/milvus.json
@@ -0,0 +1,53 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "milvus",
+ "title": "Milvus",
+ "description": "Perform operations on the Milvus Vector Database.",
+ "deprecated": false,
+ "firstVersion": "4.5.0",
+ "label": "database,ai",
+ "javaType": "org.apache.camel.component.milvus.MilvusComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-milvus",
+ "version": "4.5.0-SNAPSHOT",
+ "scheme": "milvus",
+ "extendsScheme": "",
+ "syntax": "milvus:collection",
+ "async": false,
+ "api": false,
+ "consumerOnly": false,
+ "producerOnly": true,
+ "lenientProperties": false,
+ "remote": true
+ },
+ "componentProperties": {
+ "configuration": { "index": 0, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.milvus.MilvusConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "The configuration;" },
+ "host": { "index": 1, "kind": "property", "displayName": "Host", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "The host to connect to." },
+ "lazyStartProducer": { "index": 2, "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 [...]
+ "port": { "index": 3, "kind": "property", "displayName": "Port", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 19530, "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "The port to connect to." },
+ "timeout": { "index": 4, "kind": "property", "displayName": "Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "Sets a default timeout for all requests" },
+ "token": { "index": 5, "kind": "property", "displayName": "Token", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "Sets the API key to use for authentication" },
+ "autowiredEnabled": { "index": 6, "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": {
+ "CamelMilvusAction": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "enum": [ "UPSERT", "RETRIEVE", "DELETE" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The action to be performed.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#ACTION" },
+ "CamelMilvusPointsPayloadSelector": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "io.qdrant.client.grpc.Points$WithPayloadSelector", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Payload Selector.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#PAYLOAD_SELECTOR" },
+ "CamelMilvusOperationID": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation ID.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#OPERATION_ID" },
+ "CamelMilvusOperationStatus": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation Status.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#OPERATION_STATUS" },
+ "CamelMilvusOperationStatusValue": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation Status Value.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#OPERATION_STATUS_VALUE" },
+ "CamelMilvusReadConsistency": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "io.qdrant.client.grpc.Points$ReadConsistency", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Read Consistency.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#READ_CONSISTENCY" },
+ "CamelMilvusWithPayload": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "true", "description": "Include Payload.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#INCLUDE_PAYLOAD" },
+ "CamelMilvusWithVectors": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "false", "description": "Include Vectors.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#INCLUDE_VECTORS" },
+ "CamelMilvusSize": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of elements.", "constantName": "org.apache.camel.component.milvus.Milvus$Headers#SIZE" }
+ },
+ "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 Name" },
+ "host": { "index": 1, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "The host to connect to." },
+ "port": { "index": 2, "kind": "parameter", "displayName": "Port", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": 19530, "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "The port to connect to." },
+ "timeout": { "index": 3, "kind": "parameter", "displayName": "Timeout", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "Sets a default timeout for all requests" },
+ "token": { "index": 4, "kind": "parameter", "displayName": "Token", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "Sets the API key to use for authentication" },
+ "lazyStartProducer": { "index": 5, "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-milvus/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 00000000000..a013fa59295
--- /dev/null
+++ b/components/camel-milvus/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=milvus
+groupId=org.apache.camel
+artifactId=camel-milvus
+version=4.5.0-SNAPSHOT
+projectName=Camel :: Milvus
+projectDescription=Camel Milvus support
diff --git a/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/component/milvus b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/component/milvus
new file mode 100644
index 00000000000..db784999a21
--- /dev/null
+++ b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/component/milvus
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.milvus.MilvusComponent
diff --git a/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/milvus-component b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/milvus-component
new file mode 100644
index 00000000000..df42a884122
--- /dev/null
+++ b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/milvus-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.milvus.MilvusComponentConfigurer
diff --git a/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/milvus-endpoint b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/milvus-endpoint
new file mode 100644
index 00000000000..b7865c613f4
--- /dev/null
+++ b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/milvus-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.milvus.MilvusEndpointConfigurer
diff --git a/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.milvus.MilvusConfiguration b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.milvus.MilvusConfiguration
new file mode 100644
index 00000000000..d46fe2053cd
--- /dev/null
+++ b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.component.milvus.MilvusConfiguration
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.milvus.MilvusConfigurationConfigurer
diff --git a/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/urifactory/milvus-endpoint b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/urifactory/milvus-endpoint
new file mode 100644
index 00000000000..bcf6d6fc51b
--- /dev/null
+++ b/components/camel-milvus/src/generated/resources/META-INF/services/org/apache/camel/urifactory/milvus-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.milvus.MilvusEndpointUriFactory
diff --git a/components/camel-milvus/src/main/docs/qdrant-component.adoc b/components/camel-milvus/src/main/docs/qdrant-component.adoc
new file mode 100644
index 00000000000..35a089ca5ad
--- /dev/null
+++ b/components/camel-milvus/src/main/docs/qdrant-component.adoc
@@ -0,0 +1,134 @@
+= Qdrant Component
+:doctitle: Qdrant
+:shortname: qdrant
+:artifactid: camel-qdrant
+:description: Perform operations on the Qdrant Vector Database.
+:since: 4.5
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only producer is supported
+//Manually maintained attributes
+:camel-spring-boot-name: qdrant
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The Qdrant Component provides support for interacting with the https://qdrant.tech[Qdrant Vector Database].
+
+== URI format
+
+[source]
+----
+qdrant:collection[?options]
+----
+
+Where *collection* represents a named set of points (vectors with a payload) defined in your database.
+
+
+// component-configure options: START
+
+// component-configure options: END
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+// component options: END
+
+// endpoint options: START
+
+// endpoint options: END
+
+
+== Collection Samples
+
+In the route below, we use the qdrant component to create a collection named _myCollection_ with the given parameters:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:in")
+ .setHeader(Qdrant.Headers.ACTION)
+ .constant(QdrantAction.CREATE_COLLECTION)
+ .setBody()
+ .constant(
+ Collections.VectorParams.newBuilder()
+ .setSize(2)
+ .setDistance(Collections.Distance.Cosine).build())
+ .to("qdrant:myCollection");
+----
+====
+
+== Points Samples
+
+=== Upsert
+
+In the route below we use the qdrant component to perform insert + updates (upsert) on points in the collection named _myCollection_:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:in")
+ .setHeader(Qdrant.Headers.ACTION)
+ .constant(QdrantAction.UPSERT)
+ .setBody()
+ .constant(
+ Points.PointStruct.newBuilder()
+ .setId(id(8))
+ .setVectors(VectorsFactory.vectors(List.of(3.5f, 4.5f)))
+ .putAllPayload(Map.of(
+ "foo", value("hello"),
+ "bar", value(1)))
+ .build())
+ .to("qdrant:myCollection");
+----
+====
+
+
+=== Retrieve
+
+In the route below, we use the qdrant component to retrieve information of a single point by id from the collection named _myCollection_:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:in")
+ .setHeader(Qdrant.Headers.ACTION)
+ .constant(QdrantAction.RETRIEVE)
+ .setBody()
+ .constant(PointIdFactory.id(8))
+ .to("qdrant:myCollection");
+----
+====
+
+
+
+=== Delete
+
+In the route below, we use the qdrant component to delete points from the collection named `myCollection` according to a criteria:
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("direct:in")
+ .setHeader(Qdrant.Headers.ACTION)
+ .constant(QdrantAction.DELETE)
+ .setBody()
+ .constant(ConditionFactory.matchKeyword("foo", "hello"))
+ .to("qdrant:myCollection");
+----
+====
+
+include::spring-boot:partial$starter.adoc[]
diff --git a/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/Milvus.java b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/Milvus.java
new file mode 100644
index 00000000000..ec15ec893e1
--- /dev/null
+++ b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/Milvus.java
@@ -0,0 +1,57 @@
+/*
+ * 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.milvus;
+
+import org.apache.camel.spi.Metadata;
+
+public class Milvus {
+ public static final String SCHEME = "milvus";
+
+ private Milvus() {
+ }
+
+ public static class Headers {
+ @Metadata(description = "The action to be performed.", javaType = "String", enums = "UPSERT,RETRIEVE,DELETE")
+ public static final String ACTION = "CamelMilvusAction";
+
+ @Metadata(description = "Payload Selector.", javaType = "io.qdrant.client.grpc.Points$WithPayloadSelector")
+ public static final String PAYLOAD_SELECTOR = "CamelMilvusPointsPayloadSelector";
+
+ @Metadata(description = "Operation ID.", javaType = "long")
+ public static final String OPERATION_ID = "CamelMilvusOperationID";
+
+ @Metadata(description = "Operation Status.", javaType = "String")
+ public static final String OPERATION_STATUS = "CamelMilvusOperationStatus";
+
+ @Metadata(description = "Operation Status Value.", javaType = "int")
+ public static final String OPERATION_STATUS_VALUE = "CamelMilvusOperationStatusValue";
+
+ @Metadata(description = "Read Consistency.", javaType = "io.qdrant.client.grpc.Points$ReadConsistency")
+ public static final String READ_CONSISTENCY = "CamelMilvusReadConsistency";
+
+ @Metadata(description = "Include Payload.", javaType = "boolean", defaultValue = "true")
+ public static final String INCLUDE_PAYLOAD = "CamelMilvusWithPayload";
+ public static final boolean DEFAULT_INCLUDE_PAYLOAD = true;
+
+ @Metadata(description = "Include Vectors.", javaType = "boolean", defaultValue = "false")
+ public static final String INCLUDE_VECTORS = "CamelMilvusWithVectors";
+ public static final boolean DEFAULT_INCLUDE_VECTORS = false;
+
+ @Metadata(description = "The number of elements.", javaType = "int")
+ public static final String SIZE = "CamelMilvusSize";
+ }
+}
diff --git a/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusAction.java b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusAction.java
new file mode 100644
index 00000000000..3ba9a290ac7
--- /dev/null
+++ b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusAction.java
@@ -0,0 +1,26 @@
+/*
+ * 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.milvus;
+
+public enum MilvusAction {
+ CREATE_COLLECTION,
+ CREATE_INDEX,
+ UPSERT,
+ INSERT,
+ SEARCH,
+ DELETE
+}
diff --git a/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusComponent.java b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusComponent.java
new file mode 100644
index 00000000000..878a543b81b
--- /dev/null
+++ b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusComponent.java
@@ -0,0 +1,71 @@
+/*
+ * 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.milvus;
+
+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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(Milvus.SCHEME)
+public class MilvusComponent extends DefaultComponent {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MilvusComponent.class);
+
+ @Metadata
+ private MilvusConfiguration configuration;
+
+ public MilvusComponent() {
+ this(null);
+ }
+
+ public MilvusComponent(CamelContext context) {
+ super(context);
+
+ this.configuration = new MilvusConfiguration();
+ }
+
+ public MilvusConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * The configuration;
+ */
+ public void setConfiguration(MilvusConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ protected Endpoint createEndpoint(
+ String uri,
+ String remaining,
+ Map<String, Object> parameters)
+ throws Exception {
+
+ MilvusConfiguration configuration = this.configuration.copy();
+
+ MilvusEndpoint endpoint = new MilvusEndpoint(uri, this, remaining, configuration);
+ setProperties(endpoint, parameters);
+
+ return endpoint;
+ }
+}
diff --git a/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusConfiguration.java b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusConfiguration.java
new file mode 100644
index 00000000000..802401b6e7a
--- /dev/null
+++ b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusConfiguration.java
@@ -0,0 +1,116 @@
+/*
+ * 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.milvus;
+
+import io.milvus.client.MilvusClient;
+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 MilvusConfiguration implements Cloneable {
+
+ @Metadata(defaultValue = "localhost")
+ @UriParam
+ private String host = "localhost";
+
+ @Metadata(defaultValue = "19530")
+ @UriParam
+ private int port = 19530;
+
+ @Metadata(secret = true)
+ @UriParam
+ private String token;
+
+ @UriParam
+ private long timeout = 10000L;
+
+ @Metadata(autowired = true)
+ private MilvusClient client;
+
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * The host to connect to.
+ */
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * The port to connect to.
+ */
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ /**
+ * Sets the API key to use for authentication
+ */
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ public long getTimeout() {
+ return timeout;
+ }
+
+ /**
+ * Sets a default timeout for all requests
+ */
+ public void setTimeout(long timeout) {
+ this.timeout = timeout;
+ }
+
+ public MilvusClient getClient() {
+ return client;
+ }
+
+ /**
+ * Reference to a `io.milvus.client.MilvusClient`.
+ */
+ public void setClient(MilvusClient client) {
+ this.client = client;
+ }
+
+ // ************************
+ //
+ // Clone
+ //
+ // ************************
+
+ public MilvusConfiguration copy() {
+ try {
+ return (MilvusConfiguration) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeCamelException(e);
+ }
+ }
+}
diff --git a/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusEndpoint.java b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusEndpoint.java
new file mode 100644
index 00000000000..908e72380f6
--- /dev/null
+++ b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusEndpoint.java
@@ -0,0 +1,140 @@
+/*
+ * 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.milvus;
+
+import java.util.concurrent.TimeUnit;
+
+import io.milvus.client.MilvusClient;
+import io.milvus.client.MilvusServiceClient;
+import io.milvus.param.ConnectParam;
+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 Milvus Vector Database.
+ */
+@UriEndpoint(
+ firstVersion = "4.5.0",
+ scheme = Milvus.SCHEME,
+ title = "Milvus",
+ syntax = "milvus:collection",
+ producerOnly = true,
+ category = {
+ Category.DATABASE,
+ Category.AI
+ },
+ headersClass = Milvus.Headers.class)
+public class MilvusEndpoint extends DefaultEndpoint {
+
+ @Metadata(required = true)
+ @UriPath(description = "The collection Name")
+ private final String collection;
+
+ @UriParam
+ private MilvusConfiguration configuration;
+
+ private final Object lock;
+
+ private volatile boolean closeClient;
+ private volatile MilvusClient client;
+
+ public MilvusEndpoint(
+ String endpointUri,
+ Component component,
+ String collection,
+ MilvusConfiguration configuration) {
+
+ super(endpointUri, component);
+
+ this.collection = collection;
+ this.configuration = configuration;
+
+ this.lock = new Object();
+ }
+
+ public MilvusConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ public String getCollection() {
+ return collection;
+ }
+
+ public synchronized MilvusClient getClient() {
+ if (this.client == null) {
+ synchronized (this.lock) {
+ if (this.client == null) {
+ this.client = this.configuration.getClient();
+ this.closeClient = false;
+
+ if (this.client == null) {
+ this.client = createClient();
+ this.closeClient = true;
+ }
+ }
+ }
+ }
+
+ return this.client;
+ }
+
+ @Override
+ public Producer createProducer() throws Exception {
+ return new MilvusProducer(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();
+ }
+
+ @Override
+ public void doStop() throws Exception {
+ super.doStop();
+
+ if (this.client != null && this.closeClient) {
+ this.client.close();
+ this.client = null;
+ this.closeClient = false;
+ }
+ }
+
+ private MilvusClient createClient() {
+
+ ConnectParam.Builder parameters = ConnectParam.newBuilder().withHost(configuration.getHost())
+ .withPort(configuration.getPort()).withConnectTimeout(configuration.getTimeout(), TimeUnit.MILLISECONDS);
+
+ if (configuration.getToken() != null) {
+ parameters.withToken(configuration.getToken());
+ }
+
+ return new MilvusServiceClient(parameters.build());
+ }
+}
diff --git a/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusProducer.java b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusProducer.java
new file mode 100644
index 00000000000..8a3e2a8b78b
--- /dev/null
+++ b/components/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusProducer.java
@@ -0,0 +1,192 @@
+/*
+ * 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.milvus;
+
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+import io.milvus.client.MilvusClient;
+import io.milvus.grpc.MutationResult;
+import io.milvus.param.R;
+import io.milvus.param.RpcStatus;
+import io.milvus.param.collection.CreateCollectionParam;
+import io.milvus.param.collection.LoadCollectionParam;
+import io.milvus.param.dml.DeleteParam;
+import io.milvus.param.dml.InsertParam;
+import io.milvus.param.dml.UpsertParam;
+import io.milvus.param.highlevel.dml.SearchSimpleParam;
+import io.milvus.param.highlevel.dml.response.SearchResponse;
+import io.milvus.param.index.CreateIndexParam;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.NoSuchHeaderException;
+import org.apache.camel.support.DefaultProducer;
+
+public class MilvusProducer extends DefaultProducer {
+ private MilvusClient client;
+ private ExecutorService executor;
+
+ public MilvusProducer(MilvusEndpoint endpoint) {
+ super(endpoint);
+ }
+
+ @Override
+ public MilvusEndpoint getEndpoint() {
+ return (MilvusEndpoint) super.getEndpoint();
+ }
+
+ @Override
+ public void doStart() throws Exception {
+ super.doStart();
+
+ this.client = getEndpoint().getClient();
+ }
+
+ @Override
+ public void process(Exchange exchange) {
+ final Message in = exchange.getMessage();
+ final MilvusAction action = in.getHeader(Milvus.Headers.ACTION, MilvusAction.class);
+
+ try {
+ if (action == null) {
+ throw new NoSuchHeaderException("The action is a required header", exchange, Milvus.Headers.ACTION);
+ }
+
+ switch (action) {
+ case CREATE_COLLECTION:
+ createCollection(exchange);
+ break;
+ case CREATE_INDEX:
+ createIndex(exchange);
+ break;
+ case UPSERT:
+ upsert(exchange);
+ break;
+ case INSERT:
+ insert(exchange);
+ break;
+ case SEARCH:
+ search(exchange);
+ break;
+ case DELETE:
+ delete(exchange);
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported action: " + action.name());
+ }
+ } catch (Exception e) {
+ exchange.setException(e);
+ }
+ }
+
+ // ***************************************
+ //
+ // Actions
+ //
+ // ***************************************
+
+ @SuppressWarnings({ "unchecked" })
+ private void upsert(Exchange exchange) throws Exception {
+ final Message in = exchange.getMessage();
+ final UpsertParam upsert = in.getMandatoryBody(UpsertParam.class);
+
+ R<MutationResult> result = this.client.upsert(upsert);
+
+ handleResponseStatus(result);
+ populateResponse(result, exchange);
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ private void insert(Exchange exchange) throws Exception {
+ final Message in = exchange.getMessage();
+ final InsertParam insert = in.getMandatoryBody(InsertParam.class);
+
+ R<MutationResult> result = this.client.insert(insert);
+
+ handleResponseStatus(result);
+ populateResponse(result, exchange);
+ }
+
+ private void createCollection(Exchange exchange) throws Exception {
+ final Message in = exchange.getMessage();
+ final CreateCollectionParam body = in.getMandatoryBody(CreateCollectionParam.class);
+
+ R<RpcStatus> result = this.client.createCollection(body);
+
+ handleResponseStatus(result);
+ populateResponse(result, exchange);
+
+ }
+
+
+ private void createIndex(Exchange exchange) throws Exception {
+ final Message in = exchange.getMessage();
+ final CreateIndexParam body = in.getMandatoryBody(CreateIndexParam.class);
+
+ R<RpcStatus> result = this.client.createIndex(body);
+
+ handleResponseStatus(result);
+ populateResponse(result, exchange);
+
+ }
+
+ private void search(Exchange exchange) throws Exception {
+ final Message in = exchange.getMessage();
+ final SearchSimpleParam body = in.getMandatoryBody(SearchSimpleParam.class);
+
+ this.client.loadCollection(LoadCollectionParam.newBuilder().withCollectionName(getEndpoint().getCollection()).withSyncLoad(true).build());
+ R<SearchResponse> result = this.client.search(body);
+
+ handleResponseStatus(result);
+ populateResponse(result, exchange);
+
+ }
+
+ private void delete(Exchange exchange) throws Exception {
+ final Message in = exchange.getMessage();
+ final DeleteParam body = in.getMandatoryBody(DeleteParam.class);
+
+ R<MutationResult> result = this.client.delete(body);
+
+ handleResponseStatus(result);
+ populateResponse(result, exchange);
+
+ }
+
+ // ***************************************
+ //
+ // Helpers
+ //
+ // ***************************************
+
+ private CamelContext getCamelContext() {
+ return getEndpoint().getCamelContext();
+ }
+
+ private void handleResponseStatus(R<?> r) {
+ if (r.getStatus() != R.Status.Success.getCode()) {
+ throw new RuntimeException(r.getMessage());
+ }
+ }
+
+ private void populateResponse(R<?> r, Exchange exchange) {
+ Message out = exchange.getMessage();
+ out.setHeader(Milvus.Headers.OPERATION_STATUS, r.getStatus());
+ out.setBody(r.getData());
+ }
+}
diff --git a/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusCreateCollectionTest.java b/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusCreateCollectionTest.java
new file mode 100644
index 00000000000..10ed923f5d2
--- /dev/null
+++ b/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusCreateCollectionTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.milvus;
+
+import io.milvus.grpc.DataType;
+import io.milvus.param.collection.CreateCollectionParam;
+import io.milvus.param.collection.FieldType;
+import org.apache.camel.Exchange;
+import org.apache.camel.NoSuchHeaderException;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MilvusCreateCollectionTest extends MilvusTestSupport {
+
+ @DisplayName("Tests that trying to create a collection without passing the action name triggers a failure")
+ @Test
+ public void createCollectionWithoutRequiredParameters() {
+ FieldType fieldType1 = FieldType.newBuilder()
+ .withName("userID")
+ .withDescription("user identification")
+ .withDataType(DataType.Int64)
+ .withPrimaryKey(true)
+ .withAutoID(true)
+ .build();
+
+ FieldType fieldType2 = FieldType.newBuilder()
+ .withName("userFace")
+ .withDescription("face embedding")
+ .withDataType(DataType.FloatVector)
+ .withDimension(64)
+ .build();
+
+ FieldType fieldType3 = FieldType.newBuilder()
+ .withName("userAge")
+ .withDescription("user age")
+ .withDataType(DataType.Int8)
+ .build();
+
+ CreateCollectionParam createCollectionReq = CreateCollectionParam.newBuilder()
+ .withCollectionName("test")
+ .withDescription("customer info")
+ .withShardsNum(2)
+ .withEnableDynamicField(false)
+ .addFieldType(fieldType1)
+ .addFieldType(fieldType2)
+ .addFieldType(fieldType3)
+ .build();
+
+ Exchange result = fluentTemplate.to("milvus:createCollection")
+ .withBody(
+ createCollectionReq)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isInstanceOf(NoSuchHeaderException.class);
+ }
+}
diff --git a/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusTestSupport.java b/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusTestSupport.java
new file mode 100644
index 00000000000..417354f8e1c
--- /dev/null
+++ b/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusTestSupport.java
@@ -0,0 +1,45 @@
+/*
+ * 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.milvus;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.test.infra.milvus.services.MilvusService;
+import org.apache.camel.test.infra.milvus.services.MilvusServiceFactory;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public class MilvusTestSupport extends CamelTestSupport {
+ @RegisterExtension
+ static MilvusService MILVUS = MilvusServiceFactory.createSingletonService();
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+
+ URL url = new URL(MILVUS.getMilvusEndpointUrl());
+ MilvusComponent component = context.getComponent(Milvus.SCHEME, MilvusComponent.class);
+ component.getConfiguration().setHost(url.getHost());
+ component.getConfiguration().setPort(url.getPort());
+
+ return context;
+ }
+}
diff --git a/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusUpsertTest.java b/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusUpsertTest.java
new file mode 100644
index 00000000000..f16ee8b9798
--- /dev/null
+++ b/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/MilvusUpsertTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.milvus;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.NoSuchHeaderException;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MilvusUpsertTest extends MilvusTestSupport {
+
+ @DisplayName("Tests that trying to upsert without passing the action name triggers a failure")
+ @Test
+ public void upsertWithoutRequiredParameters() {
+ Exchange result = fluentTemplate.to("milvus:upsert")
+ .withBody(null)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isInstanceOf(NoSuchHeaderException.class);
+ }
+}
diff --git a/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/it/MilvusComponentIT.java b/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/it/MilvusComponentIT.java
new file mode 100644
index 00000000000..95ee6b323e2
--- /dev/null
+++ b/components/camel-milvus/src/test/java/org/apache/camel/component/milvus/it/MilvusComponentIT.java
@@ -0,0 +1,269 @@
+/*
+ * 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.milvus.it;
+
+import io.milvus.common.clientenum.ConsistencyLevelEnum;
+import io.milvus.grpc.DataType;
+import io.milvus.param.IndexType;
+import io.milvus.param.MetricType;
+import io.milvus.param.collection.CreateCollectionParam;
+import io.milvus.param.collection.FieldType;
+import io.milvus.param.dml.DeleteParam;
+import io.milvus.param.dml.InsertParam;
+import io.milvus.param.dml.UpsertParam;
+import io.milvus.param.highlevel.dml.SearchSimpleParam;
+import io.milvus.param.highlevel.dml.response.SearchResponse;
+import io.milvus.param.index.CreateIndexParam;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.milvus.Milvus;
+import org.apache.camel.component.milvus.MilvusAction;
+import org.apache.camel.component.milvus.MilvusTestSupport;
+import org.assertj.core.util.Lists;
+import org.junit.jupiter.api.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class MilvusComponentIT extends MilvusTestSupport {
+ @Test
+ @Order(1)
+ public void createCollection() {
+ FieldType fieldType1 = FieldType.newBuilder()
+ .withName("userID")
+ .withDescription("user identification")
+ .withDataType(DataType.Int64)
+ .withPrimaryKey(true)
+ .withAutoID(true)
+ .build();
+
+ FieldType fieldType2 = FieldType.newBuilder()
+ .withName("userFace")
+ .withDescription("face embedding")
+ .withDataType(DataType.FloatVector)
+ .withDimension(64)
+ .build();
+
+ FieldType fieldType3 = FieldType.newBuilder()
+ .withName("userAge")
+ .withDescription("user age")
+ .withDataType(DataType.Int8)
+ .build();
+
+ CreateCollectionParam createCollectionReq = CreateCollectionParam.newBuilder()
+ .withCollectionName("test")
+ .withDescription("customer info")
+ .withShardsNum(2)
+ .withEnableDynamicField(false)
+ .addFieldType(fieldType1)
+ .addFieldType(fieldType2)
+ .addFieldType(fieldType3)
+ .build();
+
+ Exchange result = fluentTemplate.to("milvus:test")
+ .withHeader(Milvus.Headers.ACTION, MilvusAction.CREATE_COLLECTION)
+ .withBody(
+ createCollectionReq)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isNull();
+ }
+
+ @Test
+ @Order(2)
+ public void createIndex() {
+ CreateIndexParam createAgeIndexParam = CreateIndexParam.newBuilder()
+ .withCollectionName("test")
+ .withFieldName("userAge")
+ .withIndexType(IndexType.STL_SORT)
+ .withSyncMode(Boolean.TRUE)
+ .build();
+
+ Exchange result = fluentTemplate.to("milvus:test")
+ .withHeader(Milvus.Headers.ACTION, MilvusAction.CREATE_INDEX)
+ .withBody(
+ createAgeIndexParam)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isNull();
+
+ CreateIndexParam createVectorIndexParam = CreateIndexParam.newBuilder()
+ .withCollectionName("test")
+ .withFieldName("userFace")
+ .withIndexName("userFaceIndex")
+ .withIndexType(IndexType.IVF_FLAT)
+ .withMetricType(MetricType.L2)
+ .withExtraParam("{\"nlist\":128}")
+ .withSyncMode(Boolean.TRUE)
+ .build();
+
+ result = fluentTemplate.to("milvus:test")
+ .withHeader(Milvus.Headers.ACTION, MilvusAction.CREATE_INDEX)
+ .withBody(
+ createVectorIndexParam)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isNull();
+ }
+
+ @Test
+ @Order(3)
+ public void insert() {
+ Random ran = new Random();
+ List<Integer> ages = new ArrayList<>();
+ for (long i = 0L; i < 2; ++i) {
+ ages.add(ran.nextInt(99));
+ }
+ List<InsertParam.Field> fields = new ArrayList<>();
+ fields.add(new InsertParam.Field("userAge", ages));
+ fields.add(new InsertParam.Field("userFace", generateFloatVectors(2)));
+
+ InsertParam insertParam = InsertParam.newBuilder()
+ .withCollectionName("test")
+ .withFields(fields)
+ .build();
+
+ Exchange result = fluentTemplate.to("milvus:test")
+ .withHeader(Milvus.Headers.ACTION, MilvusAction.INSERT)
+ .withBody(
+ insertParam)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isNull();
+ }
+
+
+ @Test
+ @Order(4)
+ public void upsert() {
+ Random ran = new Random();
+ List<Integer> ages = new ArrayList<>();
+ for (long i = 0L; i < 2; ++i) {
+ ages.add(ran.nextInt(99));
+ }
+ List<UpsertParam.Field> fields = new ArrayList<>();
+ fields.add(new UpsertParam.Field("userAge", ages));
+ fields.add(new UpsertParam.Field("userFace", generateFloatVectors(2)));
+
+ UpsertParam upsertParam = UpsertParam.newBuilder()
+ .withCollectionName("test")
+ .withFields(fields)
+ .build();
+
+ Exchange result = fluentTemplate.to("milvus:test")
+ .withHeader(Milvus.Headers.ACTION, MilvusAction.UPSERT)
+ .withBody(
+ upsertParam)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).message().isEqualTo("Upsert don't support autoID==True, collection: test");
+ }
+
+ @Test
+ @Order(5)
+ public void search() {
+ SearchSimpleParam searchSimpleParam = SearchSimpleParam.newBuilder()
+ .withCollectionName("test")
+ .withVectors(generateFloatVector())
+ .withFilter("userAge>0")
+ .withLimit(100L)
+ .withOffset(0L)
+ .withOutputFields(Lists.newArrayList("userAge"))
+ .withConsistencyLevel(ConsistencyLevelEnum.STRONG)
+ .build();
+
+ Exchange result = fluentTemplate.to("milvus:test")
+ .withHeader(Milvus.Headers.ACTION, MilvusAction.SEARCH)
+ .withBody(
+ searchSimpleParam)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isNull();
+ assertThat(result.getMessage().getBody(SearchResponse.class).rowRecords.size() == 2);
+ }
+
+ @Test
+ @Order(6)
+ public void delete() {
+ DeleteParam delete = DeleteParam.newBuilder()
+ .withCollectionName("test")
+ .withExpr("userAge>0")
+ .build();
+
+ Exchange result = fluentTemplate.to("milvus:test")
+ .withHeader(Milvus.Headers.ACTION, MilvusAction.DELETE)
+ .withBody(
+ delete)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isNull();
+
+ SearchSimpleParam searchSimpleParam = SearchSimpleParam.newBuilder()
+ .withCollectionName("test")
+ .withVectors(generateFloatVector())
+ .withFilter("userAge>0")
+ .withLimit(100L)
+ .withOffset(0L)
+ .withOutputFields(Lists.newArrayList("userAge"))
+ .withConsistencyLevel(ConsistencyLevelEnum.STRONG)
+ .build();
+
+ result = fluentTemplate.to("milvus:test")
+ .withHeader(Milvus.Headers.ACTION, MilvusAction.SEARCH)
+ .withBody(
+ searchSimpleParam)
+ .request(Exchange.class);
+
+ assertThat(result).isNotNull();
+ assertThat(result.getException()).isNull();
+ assertThat(result.getMessage().getBody(SearchResponse.class).rowRecords.size() == 0);
+ }
+
+ private List<List<Float>> generateFloatVectors(int count) {
+ Random ran = new Random();
+ List<List<Float>> vectors = new ArrayList<>();
+ for (int n = 0; n < count; ++n) {
+ List<Float> vector = new ArrayList<>();
+ for (int i = 0; i < 64; ++i) {
+ vector.add(ran.nextFloat());
+ }
+ vectors.add(vector);
+ }
+
+ return vectors;
+ }
+
+ private List<Float> generateFloatVector() {
+ Random ran = new Random();
+ List<Float> vector = new ArrayList<>();
+ for (int i = 0; i < 64; ++i) {
+ vector.add(ran.nextFloat());
+ }
+ return vector;
+ }
+
+}
diff --git a/components/camel-milvus/src/test/resources/log4j2.properties b/components/camel-milvus/src/test/resources/log4j2.properties
new file mode 100644
index 00000000000..c8f8c126dd8
--- /dev/null
+++ b/components/camel-milvus/src/test/resources/log4j2.properties
@@ -0,0 +1,35 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-milvus-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n
+
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
+# To log to stdout
+#rootLogger.appenderRef.out.ref = out
+
+logger.camel-milvus.name = org.apache.camel.component.milvus
+logger.camel-milvus.level = DEBUG
diff --git a/parent/pom.xml b/parent/pom.xml
index 3c5cda1a4d9..67a73651342 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -1806,6 +1806,11 @@
<artifactId>camel-microprofile-health</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-milvus</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-mina</artifactId>
diff --git a/test-infra/camel-test-infra-milvus/pom.xml b/test-infra/camel-test-infra-milvus/pom.xml
new file mode 100644
index 00000000000..2b4ab452d8f
--- /dev/null
+++ b/test-infra/camel-test-infra-milvus/pom.xml
@@ -0,0 +1,55 @@
+<?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/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>camel-test-infra-parent</artifactId>
+ <groupId>org.apache.camel</groupId>
+ <relativePath>../camel-test-infra-parent/pom.xml</relativePath>
+ <version>4.5.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>camel-test-infra-milvus</artifactId>
+ <name>Camel :: Test Infra :: Milvus</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-infra-common</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>testcontainers</artifactId>
+ <version>${testcontainers-version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>milvus</artifactId>
+ <version>${testcontainers-version}</version>
+ </dependency>
+ </dependencies>
+
+
+</project>
diff --git a/test-infra/camel-test-infra-milvus/src/main/resources/META-INF/MANIFEST.MF b/test-infra/camel-test-infra-milvus/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/common/MilvusProperties.java b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/common/MilvusProperties.java
new file mode 100644
index 00000000000..b4e82b6ea1f
--- /dev/null
+++ b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/common/MilvusProperties.java
@@ -0,0 +1,27 @@
+/*
+ * 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.test.infra.milvus.common;
+
+public final class MilvusProperties {
+ public static final String MILVUS_ENDPOINT_URL = "milvus.endpoint.url";
+ public static final String MILVUS_CONTAINER = "milvus.container";
+
+ private MilvusProperties() {
+
+ }
+}
diff --git a/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusLocalContainerService.java b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusLocalContainerService.java
new file mode 100644
index 00000000000..3f0a5a087eb
--- /dev/null
+++ b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusLocalContainerService.java
@@ -0,0 +1,81 @@
+/*
+ * 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.test.infra.milvus.services;
+
+import java.time.Duration;
+
+import org.apache.camel.test.infra.common.LocalPropertyResolver;
+import org.apache.camel.test.infra.common.services.ContainerService;
+import org.apache.camel.test.infra.milvus.common.MilvusProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.milvus.MilvusContainer;
+import org.testcontainers.utility.DockerImageName;
+
+public class MilvusLocalContainerService implements MilvusService, ContainerService<MilvusContainer> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MilvusLocalContainerService.class);
+
+ private final MilvusContainer container;
+
+ public MilvusLocalContainerService() {
+ this(LocalPropertyResolver.getProperty(MilvusLocalContainerService.class, MilvusProperties.MILVUS_CONTAINER));
+ }
+
+ public MilvusLocalContainerService(String imageName) {
+ container = initContainer(imageName);
+ }
+
+ public MilvusLocalContainerService(MilvusContainer container) {
+ this.container = container;
+ }
+
+ protected MilvusContainer initContainer(String imageName) {
+ return new MilvusContainer(DockerImageName.parse(imageName))
+ .withStartupTimeout(Duration.ofMinutes(3L));
+ }
+
+ @Override
+ public void registerProperties() {
+ System.setProperty(MilvusProperties.MILVUS_ENDPOINT_URL, getMilvusEndpointUrl());
+ }
+
+ @Override
+ public void initialize() {
+ LOG.info("Trying to start the Milvus container");
+ container.start();
+
+ registerProperties();
+ LOG.info("Milvus instance running at {}", getMilvusEndpointUrl());
+ }
+
+ @Override
+ public void shutdown() {
+ LOG.info("Stopping the Milvus container");
+ container.stop();
+ }
+
+ @Override
+ public MilvusContainer getContainer() {
+ return container;
+ }
+
+ @Override
+ public String getMilvusEndpointUrl() {
+ return container.getEndpoint();
+ }
+}
diff --git a/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusRemoteService.java b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusRemoteService.java
new file mode 100644
index 00000000000..34b76ae5558
--- /dev/null
+++ b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusRemoteService.java
@@ -0,0 +1,42 @@
+/*
+ * 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.test.infra.milvus.services;
+
+import org.apache.camel.test.infra.milvus.common.MilvusProperties;
+
+public class MilvusRemoteService implements MilvusService {
+
+ @Override
+ public void registerProperties() {
+ // NO-OP
+ }
+
+ @Override
+ public void initialize() {
+ registerProperties();
+ }
+
+ @Override
+ public void shutdown() {
+ // NO-OP
+ }
+
+ @Override
+ public String getMilvusEndpointUrl() {
+ return System.getProperty(MilvusProperties.MILVUS_ENDPOINT_URL);
+ }
+}
diff --git a/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusService.java b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusService.java
new file mode 100644
index 00000000000..d61d0791f93
--- /dev/null
+++ b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusService.java
@@ -0,0 +1,27 @@
+/*
+ * 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.test.infra.milvus.services;
+
+import org.apache.camel.test.infra.common.services.TestService;
+
+/**
+ * Test infra service for Milvus
+ */
+public interface MilvusService extends TestService {
+
+ String getMilvusEndpointUrl();
+}
diff --git a/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusServiceFactory.java b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusServiceFactory.java
new file mode 100644
index 00000000000..51ca99ad080
--- /dev/null
+++ b/test-infra/camel-test-infra-milvus/src/test/java/org/apache/camel/test/infra/milvus/services/MilvusServiceFactory.java
@@ -0,0 +1,55 @@
+/*
+ * 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.test.infra.milvus.services;
+
+import org.apache.camel.test.infra.common.services.SimpleTestServiceBuilder;
+import org.apache.camel.test.infra.common.services.SingletonService;
+
+public final class MilvusServiceFactory {
+ private MilvusServiceFactory() {
+
+ }
+
+ public static class SingletonMilvusService extends SingletonService<MilvusService> implements MilvusService {
+
+ public SingletonMilvusService(MilvusService service, String name) {
+ super(service, name);
+ }
+
+ @Override
+ public String getMilvusEndpointUrl() {
+ return getService().getMilvusEndpointUrl();
+ }
+ }
+
+ public static SimpleTestServiceBuilder<MilvusService> builder() {
+ return new SimpleTestServiceBuilder<>("milvus");
+ }
+
+ public static MilvusService createService() {
+ return builder()
+ .addLocalMapping(MilvusLocalContainerService::new)
+ .addRemoteMapping(MilvusRemoteService::new)
+ .build();
+ }
+
+ public static MilvusService createSingletonService() {
+ return builder()
+ .addLocalMapping(() -> new SingletonMilvusService(new MilvusLocalContainerService(), "milvus"))
+ .build();
+ }
+}
diff --git a/test-infra/camel-test-infra-milvus/src/test/resources/org/apache/camel/test/infra/milvus/services/container.properties b/test-infra/camel-test-infra-milvus/src/test/resources/org/apache/camel/test/infra/milvus/services/container.properties
new file mode 100644
index 00000000000..50a0dea030a
--- /dev/null
+++ b/test-infra/camel-test-infra-milvus/src/test/resources/org/apache/camel/test/infra/milvus/services/container.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+milvus.container=milvusdb/milvus:v2.3.9
\ No newline at end of file
diff --git a/test-infra/pom.xml b/test-infra/pom.xml
index fcd9be09cf2..e4e224cd174 100644
--- a/test-infra/pom.xml
+++ b/test-infra/pom.xml
@@ -79,5 +79,6 @@
<module>camel-test-infra-cli</module>
<module>camel-test-infra-qdrant</module>
<module>camel-test-infra-ollama</module>
+ <module>camel-test-infra-milvus</module>
</modules>
</project>