Skip to content

Commit

Permalink
Merge pull request #44 from qdrant/1-10
Browse files Browse the repository at this point in the history
v1.10
  • Loading branch information
generall authored Jul 1, 2024
2 parents 084af1e + 98eafec commit 25e3b5a
Show file tree
Hide file tree
Showing 7 changed files with 606 additions and 3 deletions.
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# The version of qdrant to use to download protos
qdrantProtosVersion=v1.9.5
qdrantProtosVersion=v1.10.0

# The version of qdrant docker image to run integration tests against
qdrantVersion=v1.9.5
qdrantVersion=v1.10.0

# The version of the client to generate
packageVersion=1.9.1
packageVersion=1.10.0
101 changes: 101 additions & 0 deletions src/main/java/io/qdrant/client/QdrantClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@
import io.qdrant.client.grpc.Points.PointsOperationResponse;
import io.qdrant.client.grpc.Points.PointsSelector;
import io.qdrant.client.grpc.Points.PointsUpdateOperation;
import io.qdrant.client.grpc.Points.QueryBatchPoints;
import io.qdrant.client.grpc.Points.QueryBatchResponse;
import io.qdrant.client.grpc.Points.QueryPoints;
import io.qdrant.client.grpc.Points.QueryResponse;
import io.qdrant.client.grpc.Points.ReadConsistency;
import io.qdrant.client.grpc.Points.RecommendBatchPoints;
import io.qdrant.client.grpc.Points.RecommendBatchResponse;
Expand Down Expand Up @@ -2746,6 +2750,103 @@ public ListenableFuture<Long> countAsync(
return Futures.transform(future, response -> response.getResult().getCount(), MoreExecutors.directExecutor());
}

/**
* Universally query points.
* Covers all capabilities of search, recommend, discover, filters.
* Also enables hybrid and multi-stage queries.
*
* @param request the query request
* @return a new instance of {@link ListenableFuture}
*/
public ListenableFuture<List<ScoredPoint>> queryAsync(QueryPoints request) {
return queryAsync(request, null);
}

/**
* Universally query points.
* Covers all capabilities of search, recommend, discover, filters.
* Also enables hybrid and multi-stage queries.
*
* @param request the query request
* @param timeout the timeout for the call.
* @return a new instance of {@link ListenableFuture}
*/
public ListenableFuture<List<ScoredPoint>> queryAsync(QueryPoints request, @Nullable Duration timeout) {
Preconditions.checkArgument(
!request.getCollectionName().isEmpty(),
"Collection name must not be empty");

logger.debug("Query on '{}'", request.getCollectionName());
ListenableFuture<QueryResponse> future = getPoints(timeout).query(request);
addLogFailureCallback(future, "Query");
return Futures.transform(future, QueryResponse::getResultList, MoreExecutors.directExecutor());
}

/**
* Universally query points in batch.
* Covers all capabilities of search, recommend, discover, filters.
* Also enables hybrid and multi-stage queries.
*
* @param collectionName The name of the collection
* @param queries The queries to be performed in the batch.
* @return a new instance of {@link ListenableFuture}
*/
public ListenableFuture<List<BatchResult>> queryBatchAsync(
String collectionName,
List<QueryPoints> queries
) {
return queryBatchAsync(collectionName, queries, null, null);
}

/**
* Universally query points in batch.
* Covers all capabilities of search, recommend, discover, filters.
* Also enables hybrid and multi-stage queries.
*
* @param collectionName The name of the collection
* @param queries The queries to be performed in the batch.
* @param readConsistency Options for specifying read consistency guarantees.
* @return a new instance of {@link ListenableFuture}
*/
public ListenableFuture<List<BatchResult>> queryBatchAsync(
String collectionName,
List<QueryPoints> queries,
@Nullable ReadConsistency readConsistency
) {
return queryBatchAsync(collectionName, queries, readConsistency, null);
}

/**
* Universally query points in batch.
* Covers all capabilities of search, recommend, discover, filters.
* Also enables hybrid and multi-stage queries.
*
* @param collectionName The name of the collection
* @param queries The queries to be performed in the batch.
* @param readConsistency Options for specifying read consistency guarantees.
* @param timeout The timeout for the call.
* @return a new instance of {@link ListenableFuture}
*/
public ListenableFuture<List<BatchResult>> queryBatchAsync(
String collectionName,
List<QueryPoints> queries,
@Nullable ReadConsistency readConsistency,
@Nullable Duration timeout
) {
QueryBatchPoints.Builder requestBuilder = QueryBatchPoints.newBuilder()
.setCollectionName(collectionName)
.addAllQueryPoints(queries);

if (readConsistency != null) {
requestBuilder.setReadConsistency(readConsistency);
}

logger.debug("Query batch on '{}'", collectionName);
ListenableFuture<QueryBatchResponse> future = getPoints(timeout).queryBatch(requestBuilder.build());
addLogFailureCallback(future, "Query batch");
return Futures.transform(future, QueryBatchResponse::getResultList, MoreExecutors.directExecutor());
}

//region Snapshot Management

/**
Expand Down
182 changes: 182 additions & 0 deletions src/main/java/io/qdrant/client/QueryFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package io.qdrant.client;

import java.util.List;
import java.util.UUID;
import io.qdrant.client.grpc.Points.ContextInput;
import io.qdrant.client.grpc.Points.DiscoverInput;
import io.qdrant.client.grpc.Points.Fusion;
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.VectorInput;

import static io.qdrant.client.VectorInputFactory.vectorInput;
import static io.qdrant.client.VectorInputFactory.multiVectorInput;


/**
* Convenience methods for constructing {@link Query}
*/
public final class QueryFactory {
private QueryFactory() {
}

/**
* Creates a {@link Query} for recommendation.
*
* @param input An instance of {@link RecommendInput}
* @return a new instance of {@link Query}
*/
public static Query recommend(RecommendInput input) {
return Query.newBuilder().setRecommend(input).build();
}

/**
* Creates a {@link Query} for discovery.
*
* @param input An instance of {@link DiscoverInput}
* @return a new instance of {@link Query}
*/
public static Query discover(DiscoverInput input) {
return Query.newBuilder().setDiscover(input).build();
}

/**
* Creates a {@link Query} for context search.
*
* @param input An instance of {@link ContextInput}
* @return a new instance of {@link Query}
*/
public static Query context(ContextInput input) {
return Query.newBuilder().setContext(input).build();
}

/**
* Creates a {@link Query} for pre-fetch results fusion.
*
* @param fusion An instance of {@link Fusion}
* @return a new instance of {@link Query}
*/
public static Query fusion(Fusion fusion) {
return Query.newBuilder().setFusion(fusion).build();
}

/**
* Creates a {@link Query} to order points by a payload field.
*
* @param key Name of the payload field to order by
* @return a new instance of {@link Query}
*/
public static Query orderBy(String key) {
OrderBy orderBy = OrderBy.newBuilder().setKey(key).build();
return Query.newBuilder().setOrderBy(orderBy).build();
}

/**
* Creates a {@link Query} to order points by a payload field.
*
* @param orderBy An instance of {@link OrderBy}
* @return a new instance of {@link Query}
*/
public static Query orderBy(OrderBy orderBy) {
return Query.newBuilder().setOrderBy(orderBy).build();
}

// region Nearest search queries

/**
* Creates a {@link Query} for nearest search.
*
* @param input An instance of {@link VectorInput}
* @return a new instance of {@link Query}
*/
public static Query nearest(VectorInput input) {
return Query.newBuilder().setNearest(input).build();
}

/**
* Creates a {@link Query} from a list of floats
*
* @param values A map of vector names to values
* @return A new instance of {@link Query}
*/
public static Query nearest(List < Float > values) {
return Query.newBuilder().setNearest(vectorInput(values)).build();
}

/**
* Creates a {@link Query} from a list of floats
*
* @param values A list of values
* @return A new instance of {@link Query}
*/
public static Query nearest(float...values) {
return Query.newBuilder().setNearest(vectorInput(values)).build();
}

/**
* Creates a {@link Query} from a list of floats and integers as indices
*
* @param values The list of floats representing the vector.
* @param indices The list of integers representing the indices.
* @return A new instance of {@link Query}
*/
public static Query nearest(List < Float > values, List < Integer > indices) {
return Query.newBuilder().setNearest(vectorInput(values, indices)).build();
}

/**
* Creates a {@link Query} from a nested array of floats representing a multi
* vector
*
* @param vectors The nested array of floats.
* @return A new instance of {@link Query}
*/
public static Query nearest(float[][] vectors) {
return Query.newBuilder().setNearest(multiVectorInput(vectors)).build();
}

/**
* Creates a {@link Query} from a {@link long}
*
* @param id The point id
* @return a new instance of {@link Query}
*/
public static Query nearest(long id) {
return Query.newBuilder().setNearest(vectorInput(id)).build();
}

/**
* Creates a {@link Query} from a {@link UUID}
*
* @param id The pint id
* @return a new instance of {@link Query}
*/
public static Query nearest(UUID id) {
return Query.newBuilder().setNearest(vectorInput(id)).build();
}

/**
* Creates a {@link Query} from a {@link PointId}
*
* @param id The pint id
* @return a new instance of {@link Query}
*/
public static Query nearest(PointId id) {
return Query.newBuilder().setNearest(vectorInput(id)).build();
}

/**
* Creates a {@link Query} from a nested list of floats representing a multi
* vector
*
* @param vectors The nested list of floats.
* @return A new instance of {@link Query}
*/
public static Query nearestMultiVector(List < List < Float >> vectors) {
return Query.newBuilder().setNearest(multiVectorInput(vectors)).build();
}

// endregion
}
40 changes: 40 additions & 0 deletions src/main/java/io/qdrant/client/VectorFactory.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.qdrant.client;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.google.common.primitives.Floats;

Expand Down Expand Up @@ -49,4 +51,42 @@ public static Vector vector(List<Float> vector, List<Integer> indices) {
.setIndices(SparseIndices.newBuilder().addAllData(indices).build())
.build();
}

/**
* Creates a multi vector from a nested list of floats
*
* @param vectors The nested list of floats representing the multi vector.
* @return A new instance of {@link Vector}
*/
public static Vector multiVector(List<List<Float>> vectors) {
int vectorSize = vectors.size();
List<Float> flatVector = vectors.stream().flatMap(List::stream).collect(Collectors.toList());

return Vector.newBuilder()
.addAllData(flatVector)
.setVectorsCount(vectorSize)
.build();
}

/**
* Creates a multi vector from a nested array of floats
*
* @param vectors The nested array of floats representing the multi vector.
* @return A new instance of {@link Vector}
*/
public static Vector multiVector(float[][] vectors) {
int vectorSize = vectors.length;

List<Float> flatVector = new ArrayList<>();
for (float[] vector : vectors) {
for (float value : vector) {
flatVector.add(value);
}
}

return Vector.newBuilder()
.addAllData(flatVector)
.setVectorsCount(vectorSize)
.build();
}
}
Loading

0 comments on commit 25e3b5a

Please sign in to comment.