Skip to content

Commit 8d37efd

Browse files
Anush008Anushrusscam
authored
v1.7.0 (#13)
* feat: ShardKeyFactory * feat: ShardKeySelectorFactory * feat: shard key ops * feat: shard key ops overloads * feat: discover ops * refactor: upade discoverBatchAsync * feat: targetVectorFactory, VectorFactory * test: discover searches * refactor: VectorsFactory to use vector() * Apply suggestions from code review Co-authored-by: Russ Cam <[email protected]> * chore: review changes * docs: Update README.md version --------- Co-authored-by: Anush <[email protected]> Co-authored-by: Russ Cam <[email protected]>
1 parent dc75e03 commit 8d37efd

File tree

10 files changed

+393
-25
lines changed

10 files changed

+393
-25
lines changed

README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ Java client library with handy utility methods and overloads for interfacing wit
2323

2424
## 📥 Installation
2525

26-
> Not yet published.
27-
2826
> [!IMPORTANT]
2927
> Requires Java 8 or above.
3028
@@ -36,20 +34,20 @@ To install the library, add the following lines to your build config file.
3634
<dependency>
3735
<groupId>io.qdrant</groupId>
3836
<artifactId>client</artifactId>
39-
<version>1.7-SNAPSHOT</version>
37+
<version>1.7.0</version>
4038
</dependency>
4139
```
4240

4341
#### Scala SBT
4442

4543
```sbt
46-
libraryDependencies += "io.qdrant" % "client" % "1.7-SNAPSHOT"
44+
libraryDependencies += "io.qdrant" % "client" % "1.7.0"
4745
```
4846

4947
#### Gradle
5048

5149
```gradle
52-
implementation 'io.qdrant:client:1.7-SNAPSHOT'
50+
implementation 'io.qdrant:client:1.7.0'
5351
```
5452

5553
## 📖 Documentation

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,4 @@ publishing {
228228
repositories {
229229
mavenLocal()
230230
}
231-
}
231+
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ qdrantProtosVersion=v1.7.0
55
qdrantVersion=v1.7.0
66

77
# The version of the client to generate
8-
packageVersion=1.7-SNAPSHOT
8+
packageVersion=1.7.0

src/main/java/io/qdrant/client/QdrantClient.java

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.qdrant.client.grpc.CollectionsGrpc;
1111
import io.qdrant.client.grpc.PointsGrpc;
1212
import io.qdrant.client.grpc.SnapshotsGrpc;
13+
1314
import org.slf4j.Logger;
1415
import org.slf4j.LoggerFactory;
1516

@@ -28,8 +29,16 @@
2829
import static io.qdrant.client.grpc.Collections.CollectionOperationResponse;
2930
import static io.qdrant.client.grpc.Collections.CreateAlias;
3031
import static io.qdrant.client.grpc.Collections.CreateCollection;
32+
import static io.qdrant.client.grpc.Collections.CreateShardKeyRequest;
33+
import static io.qdrant.client.grpc.Collections.CreateShardKeyResponse;
3134
import static io.qdrant.client.grpc.Collections.DeleteAlias;
3235
import static io.qdrant.client.grpc.Collections.DeleteCollection;
36+
import static io.qdrant.client.grpc.Collections.DeleteShardKeyRequest;
37+
import static io.qdrant.client.grpc.Collections.DeleteShardKeyResponse;
38+
import static io.qdrant.client.grpc.Points.DiscoverBatchPoints;
39+
import static io.qdrant.client.grpc.Points.DiscoverBatchResponse;
40+
import static io.qdrant.client.grpc.Points.DiscoverPoints;
41+
import static io.qdrant.client.grpc.Points.DiscoverResponse;
3342
import static io.qdrant.client.grpc.Collections.GetCollectionInfoRequest;
3443
import static io.qdrant.client.grpc.Collections.GetCollectionInfoResponse;
3544
import static io.qdrant.client.grpc.Collections.ListAliasesRequest;
@@ -40,6 +49,7 @@
4049
import static io.qdrant.client.grpc.Collections.PayloadIndexParams;
4150
import static io.qdrant.client.grpc.Collections.PayloadSchemaType;
4251
import static io.qdrant.client.grpc.Collections.RenameAlias;
52+
import static io.qdrant.client.grpc.Collections.ShardKey;
4353
import static io.qdrant.client.grpc.Collections.UpdateCollection;
4454
import static io.qdrant.client.grpc.Collections.VectorParams;
4555
import static io.qdrant.client.grpc.Collections.VectorParamsMap;
@@ -665,6 +675,78 @@ public ListenableFuture<List<AliasDescription>> listAliasesAsync(@Nullable Durat
665675

666676
//endregion
667677

678+
//region ShardKey Management
679+
680+
/**
681+
* Creates a shard key for a collection.
682+
*
683+
* @param createShardKey The request object for the operation.
684+
* @return a new instance of {@link ListenableFuture}
685+
*/
686+
public ListenableFuture<CreateShardKeyResponse> createShardKeyAsync(CreateShardKeyRequest createShardKey) {
687+
return createShardKeyAsync(createShardKey, null);
688+
}
689+
690+
/**
691+
* Creates a shard key for a collection.
692+
*
693+
* @param createShardKey The request object for the operation.
694+
* @param timeout The timeout for the call.
695+
* @return a new instance of {@link ListenableFuture}
696+
*/
697+
public ListenableFuture<CreateShardKeyResponse> createShardKeyAsync(CreateShardKeyRequest createShardKey, @Nullable Duration timeout) {
698+
String collectionName = createShardKey.getCollectionName();
699+
Preconditions.checkArgument(!collectionName.isEmpty(), "Collection name must not be empty");
700+
ShardKey shardKey = createShardKey.getRequest().getShardKey();
701+
logger.debug("Create shard key '{}' for '{}'", shardKey, collectionName);
702+
703+
ListenableFuture<CreateShardKeyResponse> future = getCollections(timeout).createShardKey(createShardKey);
704+
addLogFailureCallback(future, "Create shard key");
705+
return Futures.transform(future, response -> {
706+
if (!response.getResult()) {
707+
logger.error("Shard key could not be created for '{}'", collectionName);
708+
throw new QdrantException("Shard key " + shardKey + " could not be created for " + collectionName);
709+
}
710+
return response;
711+
}, MoreExecutors.directExecutor());
712+
}
713+
714+
/**
715+
* Deletes a shard key for a collection.
716+
*
717+
* @param deleteShardKey The request object for the operation.
718+
* @return a new instance of {@link ListenableFuture}
719+
*/
720+
public ListenableFuture<DeleteShardKeyResponse> deleteShardKeyAsync(DeleteShardKeyRequest deleteShardKey) {
721+
return deleteShardKeyAsync(deleteShardKey, null);
722+
}
723+
724+
/**
725+
* Deletes a shard key for a collection.
726+
*
727+
* @param deleteShardKey The request object for the operation.
728+
* @param timeout The timeout for the call.
729+
* @return a new instance of {@link ListenableFuture}
730+
*/
731+
public ListenableFuture<DeleteShardKeyResponse> deleteShardKeyAsync(DeleteShardKeyRequest deleteShardKey, @Nullable Duration timeout) {
732+
String collectionName = deleteShardKey.getCollectionName();
733+
Preconditions.checkArgument(!collectionName.isEmpty(), "Collection name must not be empty");
734+
ShardKey shardKey = deleteShardKey.getRequest().getShardKey();
735+
logger.debug("Delete shard key '{}' for '{}'", shardKey, collectionName);
736+
737+
ListenableFuture<DeleteShardKeyResponse> future = getCollections(timeout).deleteShardKey(deleteShardKey);
738+
addLogFailureCallback(future, "Delete shard key");
739+
return Futures.transform(future, response -> {
740+
if (!response.getResult()) {
741+
logger.error("Shard key '{}' could not be deleted for '{}'", shardKey, collectionName);
742+
throw new QdrantException("Shard key " + shardKey + " could not be created for " + collectionName);
743+
}
744+
return response;
745+
}, MoreExecutors.directExecutor());
746+
}
747+
748+
//endregion
749+
668750
//region Point Management
669751

670752
/**
@@ -2153,6 +2235,88 @@ public ListenableFuture<List<PointGroup>> recommendGroupsAsync(RecommendPointGro
21532235
MoreExecutors.directExecutor());
21542236
}
21552237

2238+
/**
2239+
* Use the context and a target to find the most similar points to the target.
2240+
* Constraints by the context.
2241+
*
2242+
* @param request The discover points request
2243+
* @return a new instance of {@link ListenableFuture}
2244+
*/
2245+
public ListenableFuture<List<ScoredPoint>> discoverAsync(DiscoverPoints request) {
2246+
return discoverAsync(request, null);
2247+
}
2248+
2249+
/**
2250+
* Use the context and a target to find the most similar points to the target.
2251+
* Constraints by the context.
2252+
*
2253+
* @param request The discover points request
2254+
* @param timeout The timeout for the call.
2255+
* @return a new instance of {@link ListenableFuture}
2256+
*/
2257+
public ListenableFuture<List<ScoredPoint>> discoverAsync(DiscoverPoints request, @Nullable Duration timeout) {
2258+
String collectionName = request.getCollectionName();
2259+
Preconditions.checkArgument(!collectionName.isEmpty(), "Collection name must not be empty");
2260+
logger.debug("Discover on '{}'", collectionName);
2261+
ListenableFuture<DiscoverResponse> future = getPoints(timeout).discover(request);
2262+
addLogFailureCallback(future, "Discover");
2263+
return Futures.transform(
2264+
future,
2265+
response -> response.getResultList(),
2266+
MoreExecutors.directExecutor());
2267+
}
2268+
2269+
/**
2270+
* Use the context and a target to find the most similar points to the target in
2271+
* a batch.
2272+
* Constrained by the context.
2273+
*
2274+
* @param collectionName The name of the collection
2275+
* @param discoverSearches The list for discover point searches
2276+
* @param readConsistency Options for specifying read consistency guarantees
2277+
* @return a new instance of {@link ListenableFuture}
2278+
*/
2279+
public ListenableFuture<List<BatchResult>> discoverBatchAsync(
2280+
String collectionName,
2281+
List<DiscoverPoints> discoverSearches,
2282+
@Nullable ReadConsistency readConsistency) {
2283+
return discoverBatchAsync(collectionName, discoverSearches, readConsistency, null);
2284+
}
2285+
2286+
/**
2287+
* Use the context and a target to find the most similar points to the target in
2288+
* a batch.
2289+
* Constrained by the context.
2290+
*
2291+
* @param collectionName The name of the collection
2292+
* @param discoverSearches The list for discover point searches
2293+
* @param readConsistency Options for specifying read consistency guarantees
2294+
* @param timeout The timeout for the call.
2295+
* @return a new instance of {@link ListenableFuture}
2296+
*/
2297+
public ListenableFuture<List<BatchResult>> discoverBatchAsync(
2298+
String collectionName,
2299+
List<DiscoverPoints> discoverSearches,
2300+
@Nullable ReadConsistency readConsistency,
2301+
@Nullable Duration timeout) {
2302+
Preconditions.checkArgument(!collectionName.isEmpty(), "Collection name must not be empty");
2303+
2304+
DiscoverBatchPoints.Builder requestBuilder = DiscoverBatchPoints.newBuilder()
2305+
.setCollectionName(collectionName)
2306+
.addAllDiscoverPoints(discoverSearches);
2307+
2308+
if (readConsistency != null) {
2309+
requestBuilder.setReadConsistency(readConsistency);
2310+
}
2311+
logger.debug("Discover batch on '{}'", collectionName);
2312+
ListenableFuture<DiscoverBatchResponse> future = getPoints(timeout).discoverBatch(requestBuilder.build());
2313+
addLogFailureCallback(future, "Discover batch");
2314+
return Futures.transform(
2315+
future,
2316+
response -> response.getResultList(),
2317+
MoreExecutors.directExecutor());
2318+
}
2319+
21562320
/**
21572321
* Count the points in a collection. The count is exact
21582322
*
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.qdrant.client;
2+
3+
import io.qdrant.client.grpc.Collections.ShardKey;
4+
5+
/**
6+
* Convenience methods for constructing {@link ShardKey}
7+
*/
8+
public final class ShardKeyFactory {
9+
private ShardKeyFactory() {
10+
}
11+
12+
/**
13+
* Creates a {@link ShardKey} based on a keyword.
14+
*
15+
* @param keyword The keyword to create the shard key from
16+
* @return The {@link ShardKey} object
17+
*/
18+
public static ShardKey shardKey(String keyword) {
19+
return ShardKey.newBuilder().setKeyword(keyword).build();
20+
}
21+
22+
/**
23+
* Creates a {@link ShardKey} based on a number.
24+
*
25+
* @param number The number to create the shard key from
26+
* @return The {@link ShardKey} object
27+
*/
28+
public static ShardKey shardKey(long number) {
29+
return ShardKey.newBuilder().setNumber(number).build();
30+
}
31+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package io.qdrant.client;
2+
3+
import io.qdrant.client.grpc.Collections.ShardKey;
4+
import io.qdrant.client.grpc.Points.ShardKeySelector;
5+
6+
import static io.qdrant.client.ShardKeyFactory.shardKey;
7+
8+
import java.util.Arrays;
9+
10+
/**
11+
* Convenience methods for constructing {@link ShardKeySelector}
12+
*/
13+
public class ShardKeySelectorFactory {
14+
private ShardKeySelectorFactory() {
15+
}
16+
17+
/**
18+
* Creates a {@link ShardKeySelector} with the given shard keys.
19+
*
20+
* @param shardKeys The shard keys to include in the selector.
21+
* @return The created {@link ShardKeySelector} object.
22+
*/
23+
public static ShardKeySelector shardKeySelector(ShardKey... shardKeys) {
24+
return ShardKeySelector.newBuilder().addAllShardKeys(Arrays.asList(shardKeys)).build();
25+
}
26+
27+
/**
28+
* Creates a {@link ShardKeySelector} with the given shard key keywords.
29+
*
30+
* @param keywords The shard key keywords to include in the selector.
31+
* @return The created {@link ShardKeySelector} object.
32+
*/
33+
public static ShardKeySelector shardKeySelector(String... keywords) {
34+
ShardKeySelector.Builder builder = ShardKeySelector.newBuilder();
35+
for (String keyword : keywords) {
36+
builder.addShardKeys(shardKey(keyword));
37+
}
38+
return builder.build();
39+
}
40+
41+
/**
42+
* Creates a {@link ShardKeySelector} with the given shard key numbers.
43+
*
44+
* @param numbers The shard key numbers to include in the selector.
45+
* @return The created {@link ShardKeySelector} object.
46+
*/
47+
public static ShardKeySelector shardKeySelector(long... numbers) {
48+
ShardKeySelector.Builder builder = ShardKeySelector.newBuilder();
49+
for (long number : numbers) {
50+
builder.addShardKeys(shardKey(number));
51+
}
52+
return builder.build();
53+
}
54+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.qdrant.client;
2+
3+
import io.qdrant.client.grpc.Points.PointId;
4+
import io.qdrant.client.grpc.Points.TargetVector;
5+
import io.qdrant.client.grpc.Points.Vector;
6+
import io.qdrant.client.grpc.Points.VectorExample;
7+
8+
/**
9+
* Convenience methods for constructing {@link TargetVector}
10+
*/
11+
public class TargetVectorFactory {
12+
private TargetVectorFactory() {
13+
}
14+
15+
/**
16+
* Creates a TargetVector from a point ID
17+
* @param id The point ID to use
18+
* @return A new instance of {@link TargetVector}
19+
*/
20+
public static TargetVector targetVector(PointId id) {
21+
return TargetVector.newBuilder().setSingle(VectorExample.newBuilder().setId(id)).build();
22+
}
23+
24+
/**
25+
* Creates a TargetVector from a Vector
26+
* @param vector The Vector value to use
27+
* @return A new instance of {@link TargetVector}
28+
*/
29+
public static TargetVector targetVector(Vector vector) {
30+
return TargetVector.newBuilder().setSingle(VectorExample.newBuilder().setVector(vector)).build();
31+
}
32+
}

0 commit comments

Comments
 (0)