From fb7ab1d6431ccf7bfe2bece746c5fcb7a8a37f1d Mon Sep 17 00:00:00 2001 From: Anush008 Date: Tue, 2 Sep 2025 02:18:13 +0530 Subject: [PATCH 01/10] v1.16.0 Signed-off-by: Anush008 --- gradle.properties | 6 +-- .../java/io/qdrant/client/VectorFactory.java | 39 +++++++++++-------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/gradle.properties b/gradle.properties index 70abb120..296ff405 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ # The version of qdrant to use to download protos -qdrantProtosVersion=v1.15.0 +qdrantProtosVersion=Anush008-removed-legacy-vector-fields # The version of qdrant docker image to run integration tests against -qdrantVersion=v1.15.0 +qdrantVersion=dev # The version of the client to generate -packageVersion=1.15.0 +packageVersion=1.16.0 diff --git a/src/main/java/io/qdrant/client/VectorFactory.java b/src/main/java/io/qdrant/client/VectorFactory.java index dc5607f0..dfde007a 100644 --- a/src/main/java/io/qdrant/client/VectorFactory.java +++ b/src/main/java/io/qdrant/client/VectorFactory.java @@ -1,10 +1,12 @@ package io.qdrant.client; import com.google.common.primitives.Floats; +import io.qdrant.client.grpc.Points.DenseVector; import io.qdrant.client.grpc.Points.Document; import io.qdrant.client.grpc.Points.Image; import io.qdrant.client.grpc.Points.InferenceObject; -import io.qdrant.client.grpc.Points.SparseIndices; +import io.qdrant.client.grpc.Points.MultiDenseVector; +import io.qdrant.client.grpc.Points.SparseVector; import io.qdrant.client.grpc.Points.Vector; import java.util.ArrayList; import java.util.List; @@ -21,7 +23,9 @@ private VectorFactory() {} * @return A new instance of {@link Vector} */ public static Vector vector(List values) { - return Vector.newBuilder().addAllData(values).build(); + return Vector.newBuilder() + .setDense(DenseVector.newBuilder().addAllData(values).build()) + .build(); } /** @@ -31,7 +35,9 @@ public static Vector vector(List values) { * @return A new instance of {@link Vector} */ public static Vector vector(float... values) { - return Vector.newBuilder().addAllData(Floats.asList(values)).build(); + return Vector.newBuilder() + .setDense(DenseVector.newBuilder().addAllData(Floats.asList(values)).build()) + .build(); } /** @@ -43,8 +49,7 @@ public static Vector vector(float... values) { */ public static Vector vector(List vector, List indices) { return Vector.newBuilder() - .addAllData(vector) - .setIndices(SparseIndices.newBuilder().addAllData(indices).build()) + .setSparse(SparseVector.newBuilder().addAllValues(vector).addAllIndices(indices).build()) .build(); } @@ -85,10 +90,13 @@ public static Vector vector(InferenceObject object) { * @return A new instance of {@link Vector} */ public static Vector multiVector(List> vectors) { - int vectorSize = vectors.size(); - List flatVector = vectors.stream().flatMap(List::stream).collect(Collectors.toList()); - - return Vector.newBuilder().addAllData(flatVector).setVectorsCount(vectorSize).build(); + List denseVectors = + vectors.stream() + .map(v -> DenseVector.newBuilder().addAllData(v).build()) + .collect(Collectors.toList()); + return Vector.newBuilder() + .setMultiDense(MultiDenseVector.newBuilder().addAllVectors(denseVectors).build()) + .build(); } /** @@ -98,15 +106,12 @@ public static Vector multiVector(List> vectors) { * @return A new instance of {@link Vector} */ public static Vector multiVector(float[][] vectors) { - int vectorSize = vectors.length; - - List flatVector = new ArrayList<>(); + List denseVectors = new ArrayList<>(); for (float[] vector : vectors) { - for (float value : vector) { - flatVector.add(value); - } + denseVectors.add(DenseVector.newBuilder().addAllData(Floats.asList(vector)).build()); } - - return Vector.newBuilder().addAllData(flatVector).setVectorsCount(vectorSize).build(); + return Vector.newBuilder() + .setMultiDense(MultiDenseVector.newBuilder().addAllVectors(denseVectors).build()) + .build(); } } From 22c78ddc3bd7e7d9de91d132d89ac15a43969ca8 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sun, 7 Sep 2025 21:59:00 +0530 Subject: [PATCH 02/10] chore: Use dev Signed-off-by: Anush008 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 296ff405..166c15ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # The version of qdrant to use to download protos -qdrantProtosVersion=Anush008-removed-legacy-vector-fields +qdrantProtosVersion=dev # The version of qdrant docker image to run integration tests against qdrantVersion=dev From a5c5ca2334269ef4532c19fd72e6926eaa8b4dd1 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Tue, 9 Sep 2025 11:48:51 +0530 Subject: [PATCH 03/10] test: Use list collections to check for auth instead of health check Signed-off-by: Anush008 --- src/test/java/io/qdrant/client/ApiKeyTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/io/qdrant/client/ApiKeyTest.java b/src/test/java/io/qdrant/client/ApiKeyTest.java index 48eccf9e..3174fbb7 100644 --- a/src/test/java/io/qdrant/client/ApiKeyTest.java +++ b/src/test/java/io/qdrant/client/ApiKeyTest.java @@ -9,8 +9,8 @@ import io.grpc.ManagedChannel; import io.grpc.Status; import io.grpc.StatusRuntimeException; -import io.qdrant.client.grpc.QdrantOuterClass.HealthCheckReply; -import io.qdrant.client.grpc.QdrantOuterClass.HealthCheckRequest; +import io.qdrant.client.grpc.Collections.ListCollectionsRequest; +import io.qdrant.client.grpc.Collections.ListCollectionsResponse; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterEach; @@ -44,15 +44,14 @@ public void teardown() throws InterruptedException { @Test public void client_with_api_key_can_connect() throws ExecutionException, InterruptedException { - HealthCheckReply healthCheckReply; + ListCollectionsResponse listCollectionsResponse; try (QdrantGrpcClient grpcClient = QdrantGrpcClient.newBuilder(channel).withApiKey("password!").build()) { - healthCheckReply = - grpcClient.qdrant().healthCheck(HealthCheckRequest.getDefaultInstance()).get(); + listCollectionsResponse = + grpcClient.collections().list(ListCollectionsRequest.getDefaultInstance()).get(); } - assertNotNull(healthCheckReply.getTitle()); - assertNotNull(healthCheckReply.getVersion()); + assertNotNull(listCollectionsResponse.getCollectionsList()); } @Test @@ -61,7 +60,8 @@ public void client_without_api_key_cannot_connect() { ExecutionException executionException = assertThrows( ExecutionException.class, - () -> grpcClient.qdrant().healthCheck(HealthCheckRequest.getDefaultInstance()).get()); + () -> + grpcClient.collections().list(ListCollectionsRequest.getDefaultInstance()).get()); Throwable cause = executionException.getCause(); assertEquals(StatusRuntimeException.class, cause.getClass()); StatusRuntimeException statusRuntimeException = (StatusRuntimeException) cause; From d4a16d92974df5a6e69df1a011a4db135bf9b080 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Tue, 16 Sep 2025 01:55:37 +0530 Subject: [PATCH 04/10] feat: Added VectorOutputHelper Signed-off-by: Anush008 --- .../io/qdrant/client/VectorOutputHelper.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/main/java/io/qdrant/client/VectorOutputHelper.java diff --git a/src/main/java/io/qdrant/client/VectorOutputHelper.java b/src/main/java/io/qdrant/client/VectorOutputHelper.java new file mode 100644 index 00000000..87531de2 --- /dev/null +++ b/src/main/java/io/qdrant/client/VectorOutputHelper.java @@ -0,0 +1,103 @@ +package io.qdrant.client; + +import io.qdrant.client.grpc.Points.DenseVector; +import io.qdrant.client.grpc.Points.MultiDenseVector; +import io.qdrant.client.grpc.Points.SparseIndices; +import io.qdrant.client.grpc.Points.SparseVector; +import io.qdrant.client.grpc.Points.VectorOutput; +import java.util.ArrayList; +import java.util.List; + +/** Helper methods for extracting vector data from {@link VectorOutput}. */ +public final class VectorOutputHelper { + private VectorOutputHelper() {} + + /** + * Returns the DenseVector from the VectorOutput. + * + * @param vectorOutput the VectorOutput to extract from + * @return the DenseVector if available, null otherwise + */ + public static DenseVector getDenseVector(VectorOutput vectorOutput) { + if (vectorOutput == null) { + return null; + } + + List data = vectorOutput.getDataList(); + if (!data.isEmpty()) { + return DenseVector.newBuilder().addAllData(data).build(); + } + + if (vectorOutput.hasDense()) { + return vectorOutput.getDense(); + } + + return null; + } + + /** + * Returns the SparseVector from the VectorOutput. + * + * @param vectorOutput the VectorOutput to extract from + * @return the SparseVector if available, null otherwise + */ + public static SparseVector getSparseVector(VectorOutput vectorOutput) { + if (vectorOutput == null) { + return null; + } + + List data = vectorOutput.getDataList(); + if (!data.isEmpty()) { + if (vectorOutput.hasIndices()) { + SparseIndices indices = vectorOutput.getIndices(); + return SparseVector.newBuilder() + .addAllValues(data) + .addAllIndices(indices.getDataList()) + .build(); + } + } + + if (vectorOutput.hasSparse()) { + return vectorOutput.getSparse(); + } + + return null; + } + + /** + * Returns the MultiDenseVector from the VectorOutput. + * + * @param vectorOutput the VectorOutput to extract from + * @return the MultiDenseVector if available, null otherwise + */ + public static MultiDenseVector getMultiVector(VectorOutput vectorOutput) { + if (vectorOutput == null) { + return null; + } + + List data = vectorOutput.getDataList(); + if (!data.isEmpty()) { + int vectorsCount = vectorOutput.getVectorsCount(); + if (vectorsCount > 0) { + int vectorSize = data.size() / vectorsCount; + List vectors = new ArrayList<>(vectorsCount); + + for (int i = 0; i < vectorsCount; i++) { + int start = i * vectorSize; + int end = start + vectorSize; + List vectorData = data.subList(start, end); + + vectors.add(DenseVector.newBuilder().addAllData(vectorData).build()); + } + + return MultiDenseVector.newBuilder().addAllVectors(vectors).build(); + } + } + + if (vectorOutput.hasMultiDense()) { + return vectorOutput.getMultiDense(); + } + + return null; + } +} From a50d12d12c2fc434ef3f1c77d4068becc6c4c62e Mon Sep 17 00:00:00 2001 From: Anush008 Date: Tue, 11 Nov 2025 19:01:21 +0530 Subject: [PATCH 05/10] matchTextAny Signed-off-by: Anush008 --- .../java/io/qdrant/client/ConditionFactory.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/io/qdrant/client/ConditionFactory.java b/src/main/java/io/qdrant/client/ConditionFactory.java index 27d77750..9496894a 100644 --- a/src/main/java/io/qdrant/client/ConditionFactory.java +++ b/src/main/java/io/qdrant/client/ConditionFactory.java @@ -125,6 +125,23 @@ public static Condition matchPhrase(String field, String phrase) { .build(); } + /** + * Match records where the given field matches any word in the text. + * + * @param field The name of the field + * @param textAny The text to match + * @return a new instance of {@link Condition} + */ + public static Condition matchTextAny(String field, String textAny) { + return Condition.newBuilder() + .setField( + FieldCondition.newBuilder() + .setKey(field) + .setMatch(Match.newBuilder().setTextAny(textAny).build()) + .build()) + .build(); + } + /** * Match records where the given field matches the given boolean value. * From bbc813e79e76f753b861577333d5eb3b2ecad84e Mon Sep 17 00:00:00 2001 From: Anush008 Date: Tue, 11 Nov 2025 19:17:03 +0530 Subject: [PATCH 06/10] feat: Added new RRF Query helper. Signed-off-by: Anush008 --- src/main/java/io/qdrant/client/QueryFactory.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/io/qdrant/client/QueryFactory.java b/src/main/java/io/qdrant/client/QueryFactory.java index 22b4358c..25e74a46 100644 --- a/src/main/java/io/qdrant/client/QueryFactory.java +++ b/src/main/java/io/qdrant/client/QueryFactory.java @@ -16,6 +16,7 @@ import io.qdrant.client.grpc.Points.PointId; import io.qdrant.client.grpc.Points.Query; import io.qdrant.client.grpc.Points.RecommendInput; +import io.qdrant.client.grpc.Points.Rrf; import io.qdrant.client.grpc.Points.Sample; import io.qdrant.client.grpc.Points.VectorInput; import java.util.List; @@ -65,6 +66,16 @@ public static Query fusion(Fusion fusion) { return Query.newBuilder().setFusion(fusion).build(); } + /** + * Creates a {@link Query} for reciprocal rank fusion (RRF). + * + * @param rrf An instance of {@link Rrf} + * @return a new instance of {@link Query} + */ + public static Query rrf(Rrf rrf) { + return Query.newBuilder().setRrf(rrf).build(); + } + /** * Creates a {@link Query} to order points by a payload field. * From 92532ab2ec2fd31041e28cddacc529c455db1d1b Mon Sep 17 00:00:00 2001 From: Anush008 Date: Fri, 14 Nov 2025 14:33:47 +0530 Subject: [PATCH 07/10] chore: Added one overload for updateVectors null timeout Signed-off-by: Anush008 --- src/main/java/io/qdrant/client/QdrantClient.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/io/qdrant/client/QdrantClient.java b/src/main/java/io/qdrant/client/QdrantClient.java index 7ed2de21..68b62905 100644 --- a/src/main/java/io/qdrant/client/QdrantClient.java +++ b/src/main/java/io/qdrant/client/QdrantClient.java @@ -1212,6 +1212,16 @@ public ListenableFuture updateVectorsAsync( return updateVectorsAsync(requestBuilder.build(), timeout); } + /** + * Update named vectors for point. + * + * @param request The update point vectors request + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture updateVectorsAsync(UpdatePointVectors request) { + return updateVectorsAsync(request, null); + } + /** * Update named vectors for point. * From 1f1be8b166bf01119c6bc68924ba2ef84247fa23 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Fri, 14 Nov 2025 23:06:00 +0530 Subject: [PATCH 08/10] chore: Updated imports as per https://github.com/qdrant/qdrant/pull/7536 Signed-off-by: Anush008 --- .../io/qdrant/client/ConditionFactory.java | 40 +++++++++---------- .../io/qdrant/client/ExpressionFactory.java | 2 +- .../java/io/qdrant/client/PointIdFactory.java | 2 +- .../java/io/qdrant/client/QdrantClient.java | 4 +- .../java/io/qdrant/client/QueryFactory.java | 2 +- .../io/qdrant/client/TargetVectorFactory.java | 2 +- .../io/qdrant/client/VectorInputFactory.java | 2 +- .../java/io/qdrant/client/PointsTest.java | 2 +- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/main/java/io/qdrant/client/ConditionFactory.java b/src/main/java/io/qdrant/client/ConditionFactory.java index 9496894a..d9a04bfa 100644 --- a/src/main/java/io/qdrant/client/ConditionFactory.java +++ b/src/main/java/io/qdrant/client/ConditionFactory.java @@ -1,25 +1,25 @@ package io.qdrant.client; -import io.qdrant.client.grpc.Points.Condition; -import io.qdrant.client.grpc.Points.DatetimeRange; -import io.qdrant.client.grpc.Points.FieldCondition; -import io.qdrant.client.grpc.Points.Filter; -import io.qdrant.client.grpc.Points.GeoBoundingBox; -import io.qdrant.client.grpc.Points.GeoLineString; -import io.qdrant.client.grpc.Points.GeoPoint; -import io.qdrant.client.grpc.Points.GeoPolygon; -import io.qdrant.client.grpc.Points.GeoRadius; -import io.qdrant.client.grpc.Points.HasIdCondition; -import io.qdrant.client.grpc.Points.HasVectorCondition; -import io.qdrant.client.grpc.Points.IsEmptyCondition; -import io.qdrant.client.grpc.Points.IsNullCondition; -import io.qdrant.client.grpc.Points.Match; -import io.qdrant.client.grpc.Points.NestedCondition; -import io.qdrant.client.grpc.Points.PointId; -import io.qdrant.client.grpc.Points.Range; -import io.qdrant.client.grpc.Points.RepeatedIntegers; -import io.qdrant.client.grpc.Points.RepeatedStrings; -import io.qdrant.client.grpc.Points.ValuesCount; +import io.qdrant.client.grpc.Common.Condition; +import io.qdrant.client.grpc.Common.DatetimeRange; +import io.qdrant.client.grpc.Common.FieldCondition; +import io.qdrant.client.grpc.Common.Filter; +import io.qdrant.client.grpc.Common.GeoBoundingBox; +import io.qdrant.client.grpc.Common.GeoLineString; +import io.qdrant.client.grpc.Common.GeoPoint; +import io.qdrant.client.grpc.Common.GeoPolygon; +import io.qdrant.client.grpc.Common.GeoRadius; +import io.qdrant.client.grpc.Common.HasIdCondition; +import io.qdrant.client.grpc.Common.HasVectorCondition; +import io.qdrant.client.grpc.Common.IsEmptyCondition; +import io.qdrant.client.grpc.Common.IsNullCondition; +import io.qdrant.client.grpc.Common.Match; +import io.qdrant.client.grpc.Common.NestedCondition; +import io.qdrant.client.grpc.Common.PointId; +import io.qdrant.client.grpc.Common.Range; +import io.qdrant.client.grpc.Common.RepeatedIntegers; +import io.qdrant.client.grpc.Common.RepeatedStrings; +import io.qdrant.client.grpc.Common.ValuesCount; import java.util.List; /** Convenience methods for constructing {@link Condition} */ diff --git a/src/main/java/io/qdrant/client/ExpressionFactory.java b/src/main/java/io/qdrant/client/ExpressionFactory.java index ffaaa758..604ab2cb 100644 --- a/src/main/java/io/qdrant/client/ExpressionFactory.java +++ b/src/main/java/io/qdrant/client/ExpressionFactory.java @@ -1,6 +1,6 @@ package io.qdrant.client; -import io.qdrant.client.grpc.Points.Condition; +import io.qdrant.client.grpc.Common.Condition; import io.qdrant.client.grpc.Points.DecayParamsExpression; import io.qdrant.client.grpc.Points.DivExpression; import io.qdrant.client.grpc.Points.Expression; diff --git a/src/main/java/io/qdrant/client/PointIdFactory.java b/src/main/java/io/qdrant/client/PointIdFactory.java index 35844562..86a744d9 100644 --- a/src/main/java/io/qdrant/client/PointIdFactory.java +++ b/src/main/java/io/qdrant/client/PointIdFactory.java @@ -1,6 +1,6 @@ package io.qdrant.client; -import io.qdrant.client.grpc.Points.PointId; +import io.qdrant.client.grpc.Common.PointId; import java.util.UUID; /** Convenience methods for constructing {@link PointId} */ diff --git a/src/main/java/io/qdrant/client/QdrantClient.java b/src/main/java/io/qdrant/client/QdrantClient.java index 68b62905..a4e0b213 100644 --- a/src/main/java/io/qdrant/client/QdrantClient.java +++ b/src/main/java/io/qdrant/client/QdrantClient.java @@ -39,6 +39,8 @@ import io.qdrant.client.grpc.Collections.VectorParamsMap; import io.qdrant.client.grpc.Collections.VectorsConfig; import io.qdrant.client.grpc.CollectionsGrpc; +import io.qdrant.client.grpc.Common.Filter; +import io.qdrant.client.grpc.Common.PointId; import io.qdrant.client.grpc.JsonWithInt.Value; import io.qdrant.client.grpc.Points; import io.qdrant.client.grpc.Points.BatchResult; @@ -55,11 +57,9 @@ import io.qdrant.client.grpc.Points.DiscoverPoints; import io.qdrant.client.grpc.Points.DiscoverResponse; import io.qdrant.client.grpc.Points.FieldType; -import io.qdrant.client.grpc.Points.Filter; import io.qdrant.client.grpc.Points.GetPoints; import io.qdrant.client.grpc.Points.GetResponse; import io.qdrant.client.grpc.Points.PointGroup; -import io.qdrant.client.grpc.Points.PointId; import io.qdrant.client.grpc.Points.PointStruct; import io.qdrant.client.grpc.Points.PointVectors; import io.qdrant.client.grpc.Points.PointsIdsList; diff --git a/src/main/java/io/qdrant/client/QueryFactory.java b/src/main/java/io/qdrant/client/QueryFactory.java index 25e74a46..40a283c0 100644 --- a/src/main/java/io/qdrant/client/QueryFactory.java +++ b/src/main/java/io/qdrant/client/QueryFactory.java @@ -3,6 +3,7 @@ import static io.qdrant.client.VectorInputFactory.multiVectorInput; import static io.qdrant.client.VectorInputFactory.vectorInput; +import io.qdrant.client.grpc.Common.PointId; import io.qdrant.client.grpc.Points.ContextInput; import io.qdrant.client.grpc.Points.DiscoverInput; import io.qdrant.client.grpc.Points.Document; @@ -13,7 +14,6 @@ import io.qdrant.client.grpc.Points.Mmr; import io.qdrant.client.grpc.Points.NearestInputWithMmr; import io.qdrant.client.grpc.Points.OrderBy; -import io.qdrant.client.grpc.Points.PointId; import io.qdrant.client.grpc.Points.Query; import io.qdrant.client.grpc.Points.RecommendInput; import io.qdrant.client.grpc.Points.Rrf; diff --git a/src/main/java/io/qdrant/client/TargetVectorFactory.java b/src/main/java/io/qdrant/client/TargetVectorFactory.java index a7c50680..04cc83cd 100644 --- a/src/main/java/io/qdrant/client/TargetVectorFactory.java +++ b/src/main/java/io/qdrant/client/TargetVectorFactory.java @@ -1,6 +1,6 @@ package io.qdrant.client; -import io.qdrant.client.grpc.Points.PointId; +import io.qdrant.client.grpc.Common.PointId; import io.qdrant.client.grpc.Points.TargetVector; import io.qdrant.client.grpc.Points.Vector; import io.qdrant.client.grpc.Points.VectorExample; diff --git a/src/main/java/io/qdrant/client/VectorInputFactory.java b/src/main/java/io/qdrant/client/VectorInputFactory.java index 30d20ce6..e41dafd7 100644 --- a/src/main/java/io/qdrant/client/VectorInputFactory.java +++ b/src/main/java/io/qdrant/client/VectorInputFactory.java @@ -3,12 +3,12 @@ import static io.qdrant.client.PointIdFactory.id; import com.google.common.primitives.Floats; +import io.qdrant.client.grpc.Common.PointId; import io.qdrant.client.grpc.Points.DenseVector; import io.qdrant.client.grpc.Points.Document; import io.qdrant.client.grpc.Points.Image; import io.qdrant.client.grpc.Points.InferenceObject; import io.qdrant.client.grpc.Points.MultiDenseVector; -import io.qdrant.client.grpc.Points.PointId; import io.qdrant.client.grpc.Points.SparseVector; import io.qdrant.client.grpc.Points.VectorInput; import java.util.ArrayList; diff --git a/src/test/java/io/qdrant/client/PointsTest.java b/src/test/java/io/qdrant/client/PointsTest.java index efe460de..3828854a 100644 --- a/src/test/java/io/qdrant/client/PointsTest.java +++ b/src/test/java/io/qdrant/client/PointsTest.java @@ -25,10 +25,10 @@ import io.qdrant.client.grpc.Collections.PayloadSchemaType; import io.qdrant.client.grpc.Collections.VectorParams; import io.qdrant.client.grpc.Collections.VectorsConfig; +import io.qdrant.client.grpc.Common.Filter; import io.qdrant.client.grpc.Points; import io.qdrant.client.grpc.Points.BatchResult; import io.qdrant.client.grpc.Points.DiscoverPoints; -import io.qdrant.client.grpc.Points.Filter; import io.qdrant.client.grpc.Points.Fusion; import io.qdrant.client.grpc.Points.PointGroup; import io.qdrant.client.grpc.Points.PointStruct; From 3303e830bd30a34bee738e38352cc0c88eedaae6 Mon Sep 17 00:00:00 2001 From: Anush008 Date: Fri, 14 Nov 2025 23:07:50 +0530 Subject: [PATCH 09/10] chore: Bump image and protos to v1.16.0 Signed-off-by: Anush008 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 166c15ed..b4ca498b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ # The version of qdrant to use to download protos -qdrantProtosVersion=dev +qdrantProtosVersion=v1.16.0 # The version of qdrant docker image to run integration tests against -qdrantVersion=dev +qdrantVersion=v1.16.0 # The version of the client to generate packageVersion=1.16.0 From 94643960898f78419c6b09dadb0e56b1e142eeff Mon Sep 17 00:00:00 2001 From: Anush008 Date: Mon, 17 Nov 2025 12:08:32 +0530 Subject: [PATCH 10/10] feat: Expose getCollectionClusterInfoAsync and getCollectionClusterInfoAsync to high-level client Signed-off-by: Anush008 --- .../java/io/qdrant/client/QdrantClient.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/main/java/io/qdrant/client/QdrantClient.java b/src/main/java/io/qdrant/client/QdrantClient.java index a4e0b213..717e798f 100644 --- a/src/main/java/io/qdrant/client/QdrantClient.java +++ b/src/main/java/io/qdrant/client/QdrantClient.java @@ -10,6 +10,8 @@ import io.qdrant.client.grpc.Collections.AliasDescription; import io.qdrant.client.grpc.Collections.AliasOperations; import io.qdrant.client.grpc.Collections.ChangeAliases; +import io.qdrant.client.grpc.Collections.CollectionClusterInfoRequest; +import io.qdrant.client.grpc.Collections.CollectionClusterInfoResponse; import io.qdrant.client.grpc.Collections.CollectionDescription; import io.qdrant.client.grpc.Collections.CollectionExistsRequest; import io.qdrant.client.grpc.Collections.CollectionExistsResponse; @@ -35,6 +37,8 @@ import io.qdrant.client.grpc.Collections.RenameAlias; import io.qdrant.client.grpc.Collections.ShardKey; import io.qdrant.client.grpc.Collections.UpdateCollection; +import io.qdrant.client.grpc.Collections.UpdateCollectionClusterSetupRequest; +import io.qdrant.client.grpc.Collections.UpdateCollectionClusterSetupResponse; import io.qdrant.client.grpc.Collections.VectorParams; import io.qdrant.client.grpc.Collections.VectorParamsMap; import io.qdrant.client.grpc.Collections.VectorsConfig; @@ -400,6 +404,35 @@ public ListenableFuture getCollectionInfoAsync( future, GetCollectionInfoResponse::getResult, MoreExecutors.directExecutor()); } + /** + * Gets detailed information about a collection's cluster setup. + * + * @param collectionName The name of the collection. + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture getCollectionClusterInfoAsync( + String collectionName) { + return getCollectionClusterInfoAsync(collectionName, null); + } + + /** + * Gets detailed information about a collection's cluster setup. + * + * @param collectionName The name of the collection. + * @param timeout The timeout for the call. + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture getCollectionClusterInfoAsync( + String collectionName, @Nullable Duration timeout) { + logger.debug("Get collection cluster info for '{}'", collectionName); + CollectionClusterInfoRequest request = + CollectionClusterInfoRequest.newBuilder().setCollectionName(collectionName).build(); + ListenableFuture future = + getCollections(timeout).collectionClusterInfo(request); + addLogFailureCallback(future, "Get collection cluster info"); + return future; + } + /** * Deletes a collection and all its associated data. * @@ -511,6 +544,47 @@ public ListenableFuture updateCollectionAsync( MoreExecutors.directExecutor()); } + /** + * Update cluster setup for a collection + * + * @param updateCollectionClusterSetup The update parameters. + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture updateCollectionClusterSetupAsync( + UpdateCollectionClusterSetupRequest updateCollectionClusterSetup) { + return updateCollectionClusterSetupAsync(updateCollectionClusterSetup, null); + } + + /** + * Update cluster setup for a collection + * + * @param updateCollectionClusterSetup The update parameters. + * @param timeout The timeout for the call. + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture updateCollectionClusterSetupAsync( + UpdateCollectionClusterSetupRequest updateCollectionClusterSetup, + @Nullable Duration timeout) { + String collectionName = updateCollectionClusterSetup.getCollectionName(); + Preconditions.checkArgument(!collectionName.isEmpty(), "Collection name must not be empty"); + logger.debug("Update collection cluster setup'{}'", collectionName); + + ListenableFuture future = + getCollections(timeout).updateCollectionClusterSetup(updateCollectionClusterSetup); + addLogFailureCallback(future, "Update collection"); + return Futures.transform( + future, + response -> { + if (!response.getResult()) { + logger.error("Cluster setup of collection '{}' could not be updated", collectionName); + throw new QdrantException( + "Cluster setup of collection '" + collectionName + "' could not be updated"); + } + return response; + }, + MoreExecutors.directExecutor()); + } + /** * Check if a collection exists *