From e29c2f54ac7d942b423bee22734eec749ebdb8b2 Mon Sep 17 00:00:00 2001 From: Anush Date: Tue, 2 Jan 2024 16:32:33 +0530 Subject: [PATCH] docs: Java client usage (#489) * docs: java usage quick-start * docs: collections java usage * docs: payload java usage * docs: points java-usage * docs: search java-usage * docs: explore java usage * docs: filtering java usage * docs: storage java-usage * docs: indexing java usage * docs: snapshots java-usage * docs: list Java sdk --- .../documentation/cloud/authentication.md | 16 +- .../documentation/concepts/collections.md | 191 +++++++++ .../content/documentation/concepts/explore.md | 183 +++++++++ .../documentation/concepts/filtering.md | 386 +++++++++++++++++- .../documentation/concepts/indexing.md | 51 +++ .../content/documentation/concepts/payload.md | 150 +++++++ .../content/documentation/concepts/points.md | 234 +++++++++++ .../content/documentation/concepts/search.md | 240 +++++++++++ .../documentation/concepts/snapshots.md | 60 +++ .../content/documentation/concepts/storage.md | 82 ++++ .../content/documentation/guides/security.md | 15 +- .../content/documentation/interfaces.md | 1 + .../content/documentation/quick-start.md | 153 +++++++ qdrant-landing/static/docs/misc/java.webp | Bin 0 -> 1832 bytes 14 files changed, 1756 insertions(+), 6 deletions(-) create mode 100644 qdrant-landing/static/docs/misc/java.webp diff --git a/qdrant-landing/content/documentation/cloud/authentication.md b/qdrant-landing/content/documentation/cloud/authentication.md index aa4092ff9..87fd7052d 100644 --- a/qdrant-landing/content/documentation/cloud/authentication.md +++ b/qdrant-landing/content/documentation/cloud/authentication.md @@ -21,7 +21,7 @@ However, we recommend rotating the keys from time to time. To create additional ## Authenticate via SDK Now that you have created your first cluster and key, you might want to access Qdrant Cloud from within your application. -Our official Qdrant clients for Python, TypeScript, Go, Rust, and .NET all support the API key parameter. +Our official Qdrant clients for Python, TypeScript, Go, Rust, .NET and Java all support the API key parameter. ```bash curl \ @@ -70,3 +70,17 @@ let client = QdrantClient::from_url("xyz-example.eu-central.aws.cloud.qdrant.io: .build() .unwrap(); ``` + +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; + +QdrantClient client = + new QdrantClient( + QdrantGrpcClient.newBuilder( + "xyz-example.eu-central.aws.cloud.qdrant.io", + 6334, + true) + .withApiKey("") + .build()); +``` diff --git a/qdrant-landing/content/documentation/concepts/collections.md b/qdrant-landing/content/documentation/concepts/collections.md index c2429831f..c20b569cc 100644 --- a/qdrant-landing/content/documentation/concepts/collections.md +++ b/qdrant-landing/content/documentation/concepts/collections.md @@ -88,6 +88,19 @@ client .await?; ``` +```java +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Collections.VectorParams; +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; + +QdrantClient client = new QdrantClient( + QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client.createCollectionAsync("test_collection", + VectorParams.newBuilder().setDistance(Distance.Dot).setSize(4).build()).get(); +``` + In addition to the required options, you can also specify custom values for the following collection options: * `hnsw_config` - see [indexing](../indexing/#vector-index) for details. @@ -180,6 +193,33 @@ client .await?; ``` +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Collections.VectorParams; +import io.qdrant.client.grpc.Collections.VectorsConfig; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()) + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setVectorsConfig( + VectorsConfig.newBuilder() + .setParams( + VectorParams.newBuilder() + .setSize(100) + .setDistance(Distance.Cosine) + .build())) + .setInitFromCollection("{from_collection_name}") + .build()) + .get(); +``` + ### Collection with multiple vectors *Available as of v0.10.0* @@ -275,6 +315,27 @@ client .await?; ``` +```java +import java.util.Map; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.Distance; +import io.qdrant.client.grpc.Collections.VectorParams; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + "{collection_name}", + Map.of( + "image", VectorParams.newBuilder().setSize(4).setDistance(Distance.Dot).build(), + "text", + VectorParams.newBuilder().setSize(8).setDistance(Distance.Cosine).build())) + .get(); +``` + For rare use cases, it is possible to create a collection without any vector storage. *Available as of v1.1.1* @@ -371,6 +432,27 @@ client .await?; ``` +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Collections.CreateCollection; +import io.qdrant.client.grpc.Collections.SparseVectorConfig; +import io.qdrant.client.grpc.Collections.SparseVectorParams; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .createCollectionAsync( + CreateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setSparseVectorsConfig( + SparseVectorConfig.newBuilder() + .putMap("text", SparseVectorParams.getDefaultInstance())) + .build()) + .get(); +``` + Outside of a unique name, there are no required configuration parameters for sparse vectors. The distance function for sparse vectors is always `Dot` and does not need to be specified. @@ -395,6 +477,16 @@ client.deleteCollection("{collection_name}"); client.delete_collection("{collection_name}").await?; ``` +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client.deleteCollectionAsync("{collection_name}").get(); +``` + ### Update collection parameters Dynamic parameter updates may be helpful, for example, for more efficient initial loading of vectors. @@ -446,6 +538,18 @@ client .await?; ``` +```java +import io.qdrant.client.grpc.Collections.OptimizersConfigDiff; +import io.qdrant.client.grpc.Collections.UpdateCollection; + +client.updateCollectionAsync( + UpdateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setOptimizersConfig( + OptimizersConfigDiff.newBuilder().setIndexingThreshold(10000).build()) + .build()); +``` + The following parameters can be updated: * `optimizers_config` - see [optimizer](../optimizer/) for details. @@ -640,6 +744,46 @@ client .await?; ``` +```java +import io.qdrant.client.grpc.Collections.HnswConfigDiff; +import io.qdrant.client.grpc.Collections.QuantizationConfigDiff; +import io.qdrant.client.grpc.Collections.QuantizationType; +import io.qdrant.client.grpc.Collections.ScalarQuantization; +import io.qdrant.client.grpc.Collections.UpdateCollection; +import io.qdrant.client.grpc.Collections.VectorParamsDiff; +import io.qdrant.client.grpc.Collections.VectorParamsDiffMap; +import io.qdrant.client.grpc.Collections.VectorsConfigDiff; + +client + .updateCollectionAsync( + UpdateCollection.newBuilder() + .setCollectionName("{collection_name}") + .setHnswConfig(HnswConfigDiff.newBuilder().setEfConstruct(123).build()) + .setVectorsConfig( + VectorsConfigDiff.newBuilder() + .setParamsMap( + VectorParamsDiffMap.newBuilder() + .putMap( + "my_vector", + VectorParamsDiff.newBuilder() + .setHnswConfig( + HnswConfigDiff.newBuilder() + .setM(3) + .setEfConstruct(123) + .build()) + .build()))) + .setQuantizationConfig( + QuantizationConfigDiff.newBuilder() + .setScalar( + ScalarQuantization.newBuilder() + .setType(QuantizationType.Int8) + .setQuantile(0.8f) + .setAlwaysRam(true) + .build())) + .build()) + .get(); +``` + ## Collection info Qdrant allows determining the configuration parameters of an existing collection to better understand how the points are @@ -706,6 +850,10 @@ client.getCollection("{collection_name}"); client.collection_info("{collection_name}").await?; ``` +```java +client.getCollectionInfoAsync("{collection_name}").get(); +``` + If you insert the vectors into the collection, the `status` field may become `yellow` whilst it is optimizing. It will become `green` once all the points are successfully processed. @@ -811,6 +959,10 @@ client.updateCollectionAliases({ client.create_alias("example_collection", "production_collection").await?; ``` +```java +client.createAliasAsync("production_collection", "example_collection").get(); +``` + ### Remove alias ```http @@ -852,6 +1004,10 @@ client.updateCollectionAliases({ client.delete_alias("production_collection").await?; ``` +```java +client.deleteAliasAsync("production_collection").get(); +``` + ### Switch collection Multiple alias actions are performed atomically. @@ -914,6 +1070,11 @@ client.delete_alias("production_collection").await?; client.create_alias("example_collection", "production_collection").await?; ``` +```java +client.deleteAliasAsync("production_collection").get(); +client.createAliasAsync("production_collection", "example_collection").get(); +``` + ### List collection aliases ```http @@ -944,6 +1105,16 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?; client.list_collection_aliases("{collection_name}").await?; ``` +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client.listCollectionAliasesAsync("{collection_name}").get(); +``` + ### List all aliases ```http @@ -974,6 +1145,16 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?; client.list_aliases().await?; ``` +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client.listAliasesAsync().get(); +``` + ### List all collections ```http @@ -1003,3 +1184,13 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?; client.list_collections().await?; ``` + +```java +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client.listCollectionsAsync().get(); +``` \ No newline at end of file diff --git a/qdrant-landing/content/documentation/concepts/explore.md b/qdrant-landing/content/documentation/concepts/explore.md index 1de7b0baf..a019898a4 100644 --- a/qdrant-landing/content/documentation/concepts/explore.md +++ b/qdrant-landing/content/documentation/concepts/explore.md @@ -109,6 +109,37 @@ client .await?; ``` +```java +import java.util.List; + +import static io.qdrant.client.ConditionFactory.matchKeyword; +import static io.qdrant.client.PointIdFactory.id; +import static io.qdrant.client.VectorFactory.vector; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Points.Filter; +import io.qdrant.client.grpc.Points.RecommendPoints; +import io.qdrant.client.grpc.Points.RecommendStrategy; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .recommendAsync( + RecommendPoints.newBuilder() + .setCollectionName("{collection_name}") + .addAllPositive(List.of(id(100), id(200))) + .addAllPositiveVectors(List.of(vector(100.0f, 231.0f))) + .addAllNegative(List.of(id(718))) + .addAllPositiveVectors(List.of(vector(0.2f, 0.3f, 0.4f, 0.5f))) + .setStrategy(RecommendStrategy.AverageVector) + .setFilter(Filter.newBuilder().addMust(matchKeyword("city", "London"))) + .setLimit(3) + .build()) + .get(); +``` + Example result of this API would be ```json @@ -222,6 +253,25 @@ client .await?; ``` +```java +import java.util.List; + +import static io.qdrant.client.PointIdFactory.id; + +import io.qdrant.client.grpc.Points.RecommendPoints; + +client + .recommendAsync( + RecommendPoints.newBuilder() + .setCollectionName("{collection_name}") + .addAllPositive(List.of(id(100), id(231))) + .addAllNegative(List.of(id(718))) + .setUsing("image") + .setLimit(10) + .build()) + .get(); +``` + Parameter `using` specifies which stored vectors to use for the recommendation. ### Lookup vectors from another collection @@ -277,6 +327,31 @@ client.recommend("{collection_name}", { }); ``` +```java +import java.util.List; + +import static io.qdrant.client.PointIdFactory.id; + +import io.qdrant.client.grpc.Points.LookupLocation; +import io.qdrant.client.grpc.Points.RecommendPoints; + +client + .recommendAsync( + RecommendPoints.newBuilder() + .setCollectionName("{collection_name}") + .addAllPositive(List.of(id(100), id(231))) + .addAllNegative(List.of(id(718))) + .setUsing("image") + .setLimit(10) + .setLookupFrom( + LookupLocation.newBuilder() + .setCollectionName("{external_collection_name}") + .setVectorName("{external_vector_name}") + .build()) + .build()) + .get(); +``` + Vectors are retrieved from the external collection by ids provided in the `positive` and `negative` lists. These vectors then used to perform the recommendation in the current collection, comparing against the "using" or default vector. @@ -426,6 +501,40 @@ client .await?; ``` +```java +import java.util.List; + +import static io.qdrant.client.ConditionFactory.matchKeyword; +import static io.qdrant.client.PointIdFactory.id; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Points.Filter; +import io.qdrant.client.grpc.Points.RecommendPoints; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +Filter filter = Filter.newBuilder().addMust(matchKeyword("city", "London")).build(); + +List recommendQueries = + List.of( + RecommendPoints.newBuilder() + .addAllPositive(List.of(id(100), id(231))) + .addAllNegative(List.of(id(718))) + .setFilter(filter) + .setLimit(3) + .build(), + RecommendPoints.newBuilder() + .addAllPositive(List.of(id(200), id(67))) + .addAllNegative(List.of(id(300))) + .setFilter(filter) + .setLimit(3) + .build()); + +client.recommendBatchAsync("{collection_name}", recommendQueries, null).get(); +``` + The result of this API contains one array per recommendation requests. ```json @@ -551,6 +660,47 @@ client.discover("{collection_name}", { }); ``` +```java +import java.util.List; + +import static io.qdrant.client.PointIdFactory.id; +import static io.qdrant.client.VectorFactory.vector; + +import io.qdrant.client.QdrantClient; +import io.qdrant.client.QdrantGrpcClient; +import io.qdrant.client.grpc.Points.ContextExamplePair; +import io.qdrant.client.grpc.Points.DiscoverPoints; +import io.qdrant.client.grpc.Points.TargetVector; +import io.qdrant.client.grpc.Points.VectorExample; + +QdrantClient client = + new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build()); + +client + .discoverAsync( + DiscoverPoints.newBuilder() + .setCollectionName("{collection_name}") + .setTarget( + TargetVector.newBuilder() + .setSingle( + VectorExample.newBuilder() + .setVector(vector(0.2f, 0.1f, 0.9f, 0.7f)) + .build())) + .addAllContext( + List.of( + ContextExamplePair.newBuilder() + .setPositive(VectorExample.newBuilder().setId(id(100))) + .setNegative(VectorExample.newBuilder().setId(id(718))) + .build(), + ContextExamplePair.newBuilder() + .setPositive(VectorExample.newBuilder().setId(id(200))) + .setNegative(VectorExample.newBuilder().setId(id(300))) + .build())) + .setLimit(10) + .build()) + .get(); +``` +