From e70ea3902d96ba74992e56bfec622b811ce18a73 Mon Sep 17 00:00:00 2001 From: Arnaud Gourlay Date: Fri, 4 Oct 2024 11:18:11 +0200 Subject: [PATCH 1/4] v1.12.0 --- README.md | 4 ++-- gradle.properties | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e577abd..2082d3f 100644 --- a/README.md +++ b/README.md @@ -34,14 +34,14 @@ To install the library, add the following lines to your build config file. io.qdrant client - 1.11.0 + 1.12.0 ``` #### SBT ```sbt -libraryDependencies += "io.qdrant" % "client" % "1.11.0" +libraryDependencies += "io.qdrant" % "client" % "1.12.0" ``` #### Gradle diff --git a/gradle.properties b/gradle.properties index 01f86b6..9ecd081 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ # The version of qdrant to use to download protos -qdrantProtosVersion=v1.11.0 +qdrantProtosVersion=dev # The version of qdrant docker image to run integration tests against -qdrantVersion=v1.11.0 +qdrantVersion=dev # The version of the client to generate -packageVersion=1.11.0 +packageVersion=1.12.0 From 403e07f6a201b4b3499ff4051eedee5dd287b304 Mon Sep 17 00:00:00 2001 From: Arnaud Gourlay Date: Fri, 4 Oct 2024 11:18:25 +0200 Subject: [PATCH 2/4] distance matrix API --- .gitignore | 1 + .../java/io/qdrant/client/QdrantClient.java | 67 +++++++++++++++++++ .../java/io/qdrant/client/PointsTest.java | 36 ++++++++++ 3 files changed, 104 insertions(+) diff --git a/.gitignore b/.gitignore index b513607..761f16b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ build/ .idea/libraries/ .idea/uiDesigner.xml .idea/codeStyles/codeStyleConfig.xml +.idea/codeStyles/Project.xml *.iws *.iml *.ipr diff --git a/src/main/java/io/qdrant/client/QdrantClient.java b/src/main/java/io/qdrant/client/QdrantClient.java index e525b0c..896c040 100644 --- a/src/main/java/io/qdrant/client/QdrantClient.java +++ b/src/main/java/io/qdrant/client/QdrantClient.java @@ -40,6 +40,7 @@ import io.qdrant.client.grpc.Collections.VectorsConfig; import io.qdrant.client.grpc.CollectionsGrpc; import io.qdrant.client.grpc.JsonWithInt.Value; +import io.qdrant.client.grpc.Points; import io.qdrant.client.grpc.Points.BatchResult; import io.qdrant.client.grpc.Points.ClearPayloadPoints; import io.qdrant.client.grpc.Points.CountPoints; @@ -2804,6 +2805,72 @@ public ListenableFuture> queryGroupsAsync( future, response -> response.getResult().getGroupsList(), MoreExecutors.directExecutor()); } + // region distance matrix + + /** + * Compute distance matrix for sampled points with a pair based output format. + * + * @param request the search matrix pairs request + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture searchMatrixPairsAsync( + Points.SearchMatrixPoints request) { + return searchMatrixPairsAsync(request, null); + } + + /** + * Compute distance matrix for sampled points with a pair based output format. + * + * @param request the search matrix pairs request + * @param timeout the timeout for the call. + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture searchMatrixPairsAsync( + Points.SearchMatrixPoints request, @Nullable Duration timeout) { + Preconditions.checkArgument( + !request.getCollectionName().isEmpty(), "Collection name must not be empty"); + + logger.debug("Search matrix pairs on '{}'", request.getCollectionName()); + ListenableFuture future = + getPoints(timeout).searchMatrixPairs(request); + addLogFailureCallback(future, "Search matrix pairs"); + return Futures.transform( + future, Points.SearchMatrixPairsResponse::getResult, MoreExecutors.directExecutor()); + } + + /** + * Compute distance matrix for sampled points with an offset based output format + * + * @param request the search matrix pairs request + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture searchMatrixOffsetsAsync( + Points.SearchMatrixPoints request) { + return searchMatrixOffsetsAsync(request, null); + } + + /** + * Compute distance matrix for sampled points with an offset based output format + * + * @param request the search matrix pairs request + * @param timeout the timeout for the call. + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture searchMatrixOffsetsAsync( + Points.SearchMatrixPoints request, @Nullable Duration timeout) { + Preconditions.checkArgument( + !request.getCollectionName().isEmpty(), "Collection name must not be empty"); + + logger.debug("Search matrix offsets on '{}'", request.getCollectionName()); + ListenableFuture future = + getPoints(timeout).searchMatrixOffsets(request); + addLogFailureCallback(future, "Search matrix offsets"); + return Futures.transform( + future, Points.SearchMatrixOffsetsResponse::getResult, MoreExecutors.directExecutor()); + } + + // endregion + // region Snapshot Management /** diff --git a/src/test/java/io/qdrant/client/PointsTest.java b/src/test/java/io/qdrant/client/PointsTest.java index 9549a24..de64d68 100644 --- a/src/test/java/io/qdrant/client/PointsTest.java +++ b/src/test/java/io/qdrant/client/PointsTest.java @@ -813,6 +813,42 @@ public void queryGroups() throws ExecutionException, InterruptedException { assertEquals(1, groups.stream().filter(g -> g.getHitsCount() == 1).count()); } + @Test + public void searchMatrixOffsets() throws ExecutionException, InterruptedException { + createAndSeedCollection(testName); + + Points.SearchMatrixOffsets offsets = + client + .searchMatrixOffsetsAsync( + Points.SearchMatrixPoints.newBuilder() + .setCollectionName(testName) + .setSample(3) + .setLimit(2) + .build()) + .get(); + + // Number of ids matches the limit + assertEquals(2, offsets.getIdsCount()); + } + + @Test + public void searchMatrixPairs() throws ExecutionException, InterruptedException { + createAndSeedCollection(testName); + + Points.SearchMatrixPairs pairs = + client + .searchMatrixPairsAsync( + Points.SearchMatrixPoints.newBuilder() + .setCollectionName(testName) + .setSample(3) + .setLimit(2) + .build()) + .get(); + + // Number of ids matches the limit + assertEquals(2, pairs.getPairsCount()); + } + private void createAndSeedCollection(String collectionName) throws ExecutionException, InterruptedException { CreateCollection request = From e7262ffe28d3cb8edb14ebfc81ff265b8ef1e04f Mon Sep 17 00:00:00 2001 From: Arnaud Gourlay Date: Fri, 4 Oct 2024 11:59:29 +0200 Subject: [PATCH 3/4] add support for facets --- .../java/io/qdrant/client/QdrantClient.java | 31 +++++++++++++++ .../java/io/qdrant/client/PointsTest.java | 38 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/src/main/java/io/qdrant/client/QdrantClient.java b/src/main/java/io/qdrant/client/QdrantClient.java index 896c040..712f850 100644 --- a/src/main/java/io/qdrant/client/QdrantClient.java +++ b/src/main/java/io/qdrant/client/QdrantClient.java @@ -2805,6 +2805,37 @@ public ListenableFuture> queryGroupsAsync( future, response -> response.getResult().getGroupsList(), MoreExecutors.directExecutor()); } + /** + * Perform facet counts. For each value in the field, count the number of points that have this + * value and match the conditions. + * + * @param request the facet counts request + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture> facetAsync(Points.FacetCounts request) { + return facetAsync(request, null); + } + + /** + * Perform facet counts. For each value in the field, count the number of points that have this + * value and match the conditions. + * + * @param request the facet counts request + * @param timeout the timeout for the call. + * @return a new instance of {@link ListenableFuture} + */ + public ListenableFuture> facetAsync( + Points.FacetCounts request, @Nullable Duration timeout) { + Preconditions.checkArgument( + !request.getCollectionName().isEmpty(), "Collection name must not be empty"); + + logger.debug("Facet on '{}'", request.getCollectionName()); + ListenableFuture future = getPoints(timeout).facet(request); + addLogFailureCallback(future, "Facet"); + return Futures.transform( + future, Points.FacetResponse::getHitsList, MoreExecutors.directExecutor()); + } + // region distance matrix /** diff --git a/src/test/java/io/qdrant/client/PointsTest.java b/src/test/java/io/qdrant/client/PointsTest.java index de64d68..a999980 100644 --- a/src/test/java/io/qdrant/client/PointsTest.java +++ b/src/test/java/io/qdrant/client/PointsTest.java @@ -849,6 +849,44 @@ public void searchMatrixPairs() throws ExecutionException, InterruptedException assertEquals(2, pairs.getPairsCount()); } + @Test + public void facets() throws ExecutionException, InterruptedException { + createAndSeedCollection(testName); + + // create payload index for "foo" field + UpdateResult result = + client + .createPayloadIndexAsync( + testName, "foo", PayloadSchemaType.Keyword, null, null, null, null) + .get(); + + assertEquals(UpdateStatus.Completed, result.getStatus()); + + List facets = + client + .facetAsync( + Points.FacetCounts.newBuilder() + .setCollectionName(testName) + .setKey("foo") + .setLimit(2) + .build()) + .get(); + + // Number of facets matches the limit + assertEquals(2, facets.size()); + // validate hits + assertEquals( + 1, + facets.stream() + .filter(f -> f.getValue().getStringValue().equals("hello") && f.getCount() == 1) + .count()); + assertEquals( + 1, + facets.stream() + .filter(f -> f.getValue().getStringValue().equals("goodbye") && f.getCount() == 1) + .count()); + } + private void createAndSeedCollection(String collectionName) throws ExecutionException, InterruptedException { CreateCollection request = From f73037898b33f47abf14ff3c6be36bc4987901a0 Mon Sep 17 00:00:00 2001 From: Arnaud Gourlay Date: Tue, 8 Oct 2024 16:48:45 +0200 Subject: [PATCH 4/4] bump version after release --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 9ecd081..32efcbd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ # The version of qdrant to use to download protos -qdrantProtosVersion=dev +qdrantProtosVersion=v1.12.0 # The version of qdrant docker image to run integration tests against -qdrantVersion=dev +qdrantVersion=v1.12.0 # The version of the client to generate packageVersion=1.12.0