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 =