mirror of
https://github.com/qdrant/landing_page.git
synced 2026-09-29 16:08:32 +02:00
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
This commit is contained in:
@@ -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("<paste-your-api-key-here>")
|
||||
.build());
|
||||
```
|
||||
|
||||
@@ -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();
|
||||
```
|
||||
@@ -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<RecommendPoints> 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();
|
||||
```
|
||||
|
||||
<aside role="status">
|
||||
Notes about discovery search:
|
||||
|
||||
@@ -639,6 +789,39 @@ client.discover("{collection_name}", {
|
||||
});
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
|
||||
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.VectorExample;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.discoverAsync(
|
||||
DiscoverPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.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();
|
||||
```
|
||||
|
||||
<aside role="status">
|
||||
Notes about context search:
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?;
|
||||
|
||||
client
|
||||
.scroll(&ScrollPoints {
|
||||
collection_name: "test_collection".to_string(),
|
||||
collection_name: "{collection_name}".to_string(),
|
||||
filter: Some(Filter::must([
|
||||
Condition::matches("city", "london".to_string()),
|
||||
Condition::matches("color", "red".to_string()),
|
||||
@@ -115,6 +115,32 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addAllMust(
|
||||
List.of(matchKeyword("city", "London"), matchKeyword("color", "Red")))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Filtered points would be:
|
||||
|
||||
```json
|
||||
@@ -180,7 +206,7 @@ use qdrant_client::qdrant::{Condition, Filter, ScrollPoints};
|
||||
|
||||
client
|
||||
.scroll(&ScrollPoints {
|
||||
collection_name: "test_collection".to_string(),
|
||||
collection_name: "{collection_name}".to_string(),
|
||||
filter: Some(Filter::should([
|
||||
Condition::matches("city", "london".to_string()),
|
||||
Condition::matches("color", "red".to_string()),
|
||||
@@ -190,6 +216,26 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
import java.util.List;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addAllShould(
|
||||
List.of(matchKeyword("city", "London"), matchKeyword("color", "Red")))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Filtered points would be:
|
||||
|
||||
```json
|
||||
@@ -254,7 +300,7 @@ use qdrant_client::qdrant::{Condition, Filter, ScrollPoints};
|
||||
|
||||
client
|
||||
.scroll(&ScrollPoints {
|
||||
collection_name: "test_collection".to_string(),
|
||||
collection_name: "{collection_name}".to_string(),
|
||||
filter: Some(Filter::must_not([
|
||||
Condition::matches("city", "london".to_string()),
|
||||
Condition::matches("color", "red".to_string()),
|
||||
@@ -264,6 +310,27 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addAllMustNot(
|
||||
List.of(matchKeyword("city", "London"), matchKeyword("color", "Red")))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Filtered points would be:
|
||||
|
||||
```json
|
||||
@@ -343,6 +410,25 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addMust(matchKeyword("city", "London"))
|
||||
.addMustNot(matchKeyword("color", "Red"))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Filtered points would be:
|
||||
|
||||
```json
|
||||
@@ -429,6 +515,34 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.filter;
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addMustNot(
|
||||
filter(
|
||||
Filter.newBuilder()
|
||||
.addAllMust(
|
||||
List.of(
|
||||
matchKeyword("city", "London"),
|
||||
matchKeyword("color", "Red")))
|
||||
.build()))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Filtered points would be:
|
||||
|
||||
```json
|
||||
@@ -475,6 +589,10 @@ models.FieldCondition(
|
||||
Condition::matches("color", "red".to_string())
|
||||
```
|
||||
|
||||
```java
|
||||
matchKeyword("color", "Red");
|
||||
```
|
||||
|
||||
For the other types, the match condition will look exactly the same, except for the type used:
|
||||
|
||||
```json
|
||||
@@ -504,6 +622,12 @@ models.FieldCondition(
|
||||
Condition::matches("count", 0)
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.match;
|
||||
|
||||
match("count", 0);
|
||||
```
|
||||
|
||||
The simplest kind of condition is one that checks if the stored value equals the given one.
|
||||
If several values are stored, at least one of them should match the condition.
|
||||
You can apply it to [keyword](../payload/#keyword), [integer](../payload/#integer) and [bool](../payload/#bool) payloads.
|
||||
@@ -546,6 +670,12 @@ FieldCondition(
|
||||
Condition::matches("color", vec!["black".to_string(), "yellow".to_string()])
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeywords;
|
||||
|
||||
matchKeywords("color", List.of("black", "yellow"))
|
||||
```
|
||||
|
||||
In this example, the condition will be satisfied if the stored value is either `black` or `yellow`.
|
||||
|
||||
If the stored value is an array, it should have at least one value matching any of the given values. E.g. if the stored value is `["black", "green"]`, the condition will be satisfied, because `"black"` is in `["black", "yellow"]`.
|
||||
@@ -593,6 +723,12 @@ Condition::matches(
|
||||
)
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchExceptKeywords;
|
||||
|
||||
matchExceptKeywords("color", List.of("black", "yellow"));
|
||||
```
|
||||
|
||||
In this example, the condition will be satisfied if the stored value is neither `black` nor `yellow`.
|
||||
|
||||
If the stored value is an array, it should have at least one value not matching any of the given values. E.g. if the stored value is `["black", "green"]`, the condition will be satisfied, because `"green"` does not match `"black"` nor `"yellow"`.
|
||||
@@ -707,6 +843,24 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addShould(matchKeyword("country.name", "Germany"))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
You can also search through arrays by projecting inner values using the `[]` syntax.
|
||||
|
||||
```http
|
||||
@@ -780,6 +934,28 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.range;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.Range;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addShould(
|
||||
range(
|
||||
"country.cities[].population",
|
||||
Range.newBuilder().setGte(9.0).build()))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
This query would only output the point with id 2 as only Japan has a city with population greater than 9.0.
|
||||
|
||||
And the leaf nested field can also be an array.
|
||||
@@ -842,6 +1018,24 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addShould(matchKeyword("country.cities[].sightseeing", "Germany"))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
This query would only output the point with id 2 as only Japan has a city with the "Osaka castke" as part of the sightseeing.
|
||||
|
||||
### Nested object filter
|
||||
@@ -935,7 +1129,7 @@ use qdrant_client::qdrant::{Condition, Filter, ScrollPoints};
|
||||
|
||||
client
|
||||
.scroll(&ScrollPoints {
|
||||
collection_name: "test_collection".to_string(),
|
||||
collection_name: "{collection_name}".to_string(),
|
||||
filter: Some(Filter::must([
|
||||
Condition::matches("diet[].food", "meat".to_string()),
|
||||
Condition::matches("diet[].likes", true),
|
||||
@@ -945,6 +1139,33 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.match;
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addAllMust(
|
||||
List.of(matchKeyword("diet[].food", "meat"), match("diet[].likes", true)))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
This happens because both points are matching the two conditions:
|
||||
|
||||
- the "t-rex" matches food=meat on `diet[1].food` and likes=true on `diet[1].likes`
|
||||
@@ -1059,6 +1280,35 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.match;
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
import static io.qdrant.client.ConditionFactory.nested;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addMust(
|
||||
nested(
|
||||
"diet",
|
||||
Filter.newBuilder()
|
||||
.addAllMust(
|
||||
List.of(
|
||||
matchKeyword("food", "meat"), match("likes", true)))
|
||||
.build()))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
The matching logic is modified to be applied at the level of an array element within the payload.
|
||||
|
||||
Nested filters work in the same way as if the nested filter was applied to a single element of the array at a time.
|
||||
@@ -1177,6 +1427,38 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.hasId;
|
||||
import static io.qdrant.client.ConditionFactory.match;
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
import static io.qdrant.client.ConditionFactory.nested;
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addMust(
|
||||
nested(
|
||||
"diet",
|
||||
Filter.newBuilder()
|
||||
.addAllMust(
|
||||
List.of(
|
||||
matchKeyword("food", "meat"), match("likes", true)))
|
||||
.build()))
|
||||
.addMust(hasId(id(1)))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
### Full Text Match
|
||||
|
||||
*Available as of v0.10.0*
|
||||
@@ -1218,6 +1500,12 @@ models.FieldCondition(
|
||||
Condition::matches("description", "good cheap".to_string())
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchText;
|
||||
|
||||
matchText("description", "good cheap");
|
||||
```
|
||||
|
||||
If the query has several words, then the condition will be satisfied only if all of them are present in the text.
|
||||
|
||||
### Range
|
||||
@@ -1270,6 +1558,14 @@ Condition::range(
|
||||
)
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.range;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Range;
|
||||
|
||||
range("price", Range.newBuilder().setGte(100.0).setLte(450).build());
|
||||
```
|
||||
|
||||
The `range` condition sets the range of possible values for stored payload values.
|
||||
If several values are stored, at least one of them should match the condition.
|
||||
|
||||
@@ -1350,6 +1646,12 @@ Condition::geo_bounding_box(
|
||||
)
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.geoBoundingBox;
|
||||
|
||||
geoBoundingBox("location", 52.520711, 13.403683, 52.495862, 13.455868);
|
||||
```
|
||||
|
||||
It matches with `location`s inside a rectangle with the coordinates of the upper left corner in `bottom_right` and the coordinates of the lower right corner in `top_left`.
|
||||
|
||||
#### Geo Radius
|
||||
@@ -1406,6 +1708,12 @@ Condition::geo_radius(
|
||||
)
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.geoRadius;
|
||||
|
||||
geoRadius("location", 52.520711, 13.403683, 1000.0f);
|
||||
```
|
||||
|
||||
It matches with `location`s inside a circle with the `center` at the center and a radius of `radius` meters.
|
||||
|
||||
If several values are stored, at least one of them should match the condition.
|
||||
@@ -1614,6 +1922,35 @@ Condition::geo_polygon(
|
||||
)
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.geoPolygon;
|
||||
|
||||
import io.qdrant.client.grpc.Points.GeoLineString;
|
||||
import io.qdrant.client.grpc.Points.GeoPoint;
|
||||
|
||||
geoPolygon(
|
||||
"location",
|
||||
GeoLineString.newBuilder()
|
||||
.addAllPoints(
|
||||
List.of(
|
||||
GeoPoint.newBuilder().setLon(-70.0).setLat(-70.0).build(),
|
||||
GeoPoint.newBuilder().setLon(60.0).setLat(-70.0).build(),
|
||||
GeoPoint.newBuilder().setLon(60.0).setLat(60.0).build(),
|
||||
GeoPoint.newBuilder().setLon(-70.0).setLat(60.0).build(),
|
||||
GeoPoint.newBuilder().setLon(-70.0).setLat(-70.0).build()))
|
||||
.build(),
|
||||
List.of(
|
||||
GeoLineString.newBuilder()
|
||||
.addAllPoints(
|
||||
List.of(
|
||||
GeoPoint.newBuilder().setLon(-65.0).setLat(-65.0).build(),
|
||||
GeoPoint.newBuilder().setLon(0.0).setLat(-65.0).build(),
|
||||
GeoPoint.newBuilder().setLon(0.0).setLat(0.0).build(),
|
||||
GeoPoint.newBuilder().setLon(-65.0).setLat(0.0).build(),
|
||||
GeoPoint.newBuilder().setLon(-65.0).setLat(-65.0).build()))
|
||||
.build()));
|
||||
```
|
||||
|
||||
A match is considered any point location inside or on the boundaries of the given polygon's exterior but not inside any interiors.
|
||||
|
||||
If several location values are stored for a point, then any of them matching will include that point as a candidate in the resultset.
|
||||
@@ -1667,6 +2004,14 @@ Condition::values_count(
|
||||
)
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.valuesCount;
|
||||
|
||||
import io.qdrant.client.grpc.Points.ValuesCount;
|
||||
|
||||
valuesCount("comments", ValuesCount.newBuilder().setGt(2).build());
|
||||
```
|
||||
|
||||
The result would be:
|
||||
|
||||
```json
|
||||
@@ -1706,6 +2051,12 @@ models.IsEmptyCondition(
|
||||
Condition::is_empty("reports")
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.isEmpty;
|
||||
|
||||
isEmpty("reports");
|
||||
```
|
||||
|
||||
This condition will match all records where the field `reports` either does not exist, or has `null` or `[]` value.
|
||||
|
||||
<aside role="status">The <b>IsEmpty</b> is often useful together with the logical negation <b>must_not</b>. In this case all non-empty values will be selected.</aside>
|
||||
@@ -1741,6 +2092,12 @@ models.IsNullCondition(
|
||||
Condition::is_null("reports")
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.isNull;
|
||||
|
||||
isNull("reports");
|
||||
```
|
||||
|
||||
This condition will match all records where the field `reports` exists and has `NULL` value.
|
||||
|
||||
|
||||
@@ -1796,6 +2153,27 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.hasId;
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(
|
||||
Filter.newBuilder()
|
||||
.addMust(hasId(List.of(id(1), id(3), id(5), id(7), id(9), id(11))))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Filtered points would be:
|
||||
|
||||
```json
|
||||
|
||||
@@ -72,6 +72,26 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Collections.PayloadSchemaType;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.createPayloadIndexAsync(
|
||||
"{collection_name}",
|
||||
"name_of_the_field_to_index",
|
||||
PayloadSchemaType.Keyword,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null)
|
||||
.get();
|
||||
```
|
||||
|
||||
Available field types are:
|
||||
|
||||
* `keyword` - for [keyword](../payload/#keyword) payload, affects [Match](../filtering/#match) filtering conditions.
|
||||
@@ -176,6 +196,37 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Collections.PayloadIndexParams;
|
||||
import io.qdrant.client.grpc.Collections.PayloadSchemaType;
|
||||
import io.qdrant.client.grpc.Collections.TextIndexParams;
|
||||
import io.qdrant.client.grpc.Collections.TokenizerType;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.createPayloadIndexAsync(
|
||||
"{collection_name}",
|
||||
"name_of_the_field_to_index",
|
||||
PayloadSchemaType.Text,
|
||||
PayloadIndexParams.newBuilder()
|
||||
.setTextIndexParams(
|
||||
TextIndexParams.newBuilder()
|
||||
.setTokenizer(TokenizerType.Word)
|
||||
.setMaxTokenLen(2)
|
||||
.setMaxTokenLen(10)
|
||||
.setLowercase(true)
|
||||
.build())
|
||||
.build(),
|
||||
null,
|
||||
null,
|
||||
null)
|
||||
.get();
|
||||
```
|
||||
|
||||
Available tokenizers are:
|
||||
|
||||
* `word` - splits the string into words, separated by spaces, punctuation marks, and special characters.
|
||||
|
||||
@@ -276,6 +276,49 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.ValueFactory.value;
|
||||
import static io.qdrant.client.VectorsFactory.vectors;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.PointStruct;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.upsertAsync(
|
||||
"{collection_name}",
|
||||
List.of(
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(1))
|
||||
.setVectors(vectors(0.05f, 0.61f, 0.76f, 0.74f))
|
||||
.putAllPayload(Map.of("city", value("Berlin"), "price", value(1.99)))
|
||||
.build(),
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(2))
|
||||
.setVectors(vectors(0.19f, 0.81f, 0.75f, 0.11f))
|
||||
.putAllPayload(
|
||||
Map.of("city", list(List.of(value("Berlin"), value("London")))))
|
||||
.build(),
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(3))
|
||||
.setVectors(vectors(0.36f, 0.55f, 0.47f, 0.94f))
|
||||
.putAllPayload(
|
||||
Map.of(
|
||||
"city",
|
||||
list(List.of(value("Berlin"), value("London"))),
|
||||
"price",
|
||||
list(List.of(value(1.99), value(2.99)))))
|
||||
.build()))
|
||||
.get();
|
||||
```
|
||||
|
||||
## Update payload
|
||||
|
||||
### Set payload
|
||||
@@ -344,6 +387,24 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.ValueFactory.value;
|
||||
|
||||
client
|
||||
.setPayloadAsync(
|
||||
"{collection_name}",
|
||||
Map.of("property1", value("string"), "property2", value("string")),
|
||||
List.of(id(0), id(3), id(10)),
|
||||
true,
|
||||
null,
|
||||
null)
|
||||
.get();
|
||||
```
|
||||
|
||||
You don't need to know the ids of the points you want to modify. The alternative
|
||||
is to use filters.
|
||||
|
||||
@@ -430,6 +491,23 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.Map;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
import static io.qdrant.client.ValueFactory.value;
|
||||
|
||||
client
|
||||
.setPayloadAsync(
|
||||
"{collection_name}",
|
||||
Map.of("property1", value("string"), "property2", value("string")),
|
||||
Filter.newBuilder().addMust(matchKeyword("color", "red")).build(),
|
||||
true,
|
||||
null,
|
||||
null)
|
||||
.get();
|
||||
```
|
||||
|
||||
### Overwrite payload
|
||||
|
||||
Fully replace any existing payload with the given one.
|
||||
@@ -496,6 +574,23 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.ValueFactory.value;
|
||||
|
||||
client
|
||||
.overwritePayloadAsync(
|
||||
"{collection_name}",
|
||||
Map.of("property1", value("string"), "property2", value("string")),
|
||||
List.of(id(0), id(3), id(10)),
|
||||
true,
|
||||
null,
|
||||
null)
|
||||
.get();
|
||||
```
|
||||
|
||||
Like [set payload](#set-payload), you don't need to know the ids of the points
|
||||
you want to modify. The alternative is to use filters.
|
||||
|
||||
@@ -546,6 +641,16 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
|
||||
client
|
||||
.clearPayloadAsync("{collection_name}", List.of(id(0), id(3), id(100)), true, null, null)
|
||||
.get();
|
||||
```
|
||||
|
||||
<aside role="status">
|
||||
You can also use <code>models.FilterSelector</code> to remove the points matching given filter criteria, instead of providing the ids.
|
||||
</aside>
|
||||
@@ -599,6 +704,22 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
|
||||
client
|
||||
.deletePayloadAsync(
|
||||
"{collection_name}",
|
||||
List.of("color", "price"),
|
||||
List.of(id(0), id(3), id(100)),
|
||||
true,
|
||||
null,
|
||||
null)
|
||||
.get();
|
||||
```
|
||||
|
||||
Alternatively, you can use filters to delete payload keys from the points.
|
||||
|
||||
```http
|
||||
@@ -669,6 +790,22 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
client
|
||||
.deletePayloadAsync(
|
||||
"{collection_name}",
|
||||
List.of("color", "price"),
|
||||
Filter.newBuilder().addMust(matchKeyword("color", "red")).build(),
|
||||
true,
|
||||
null,
|
||||
null)
|
||||
.get();
|
||||
```
|
||||
|
||||
## Payload indexing
|
||||
|
||||
To search more efficiently with filters, Qdrant allows you to create indexes for payload fields by specifying the name and type of field it is intended to be.
|
||||
@@ -721,6 +858,19 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.grpc.Collections.PayloadSchemaType;
|
||||
|
||||
client.createPayloadIndexAsync(
|
||||
"{collection_name}",
|
||||
"name_of_the_field_to_index",
|
||||
PayloadSchemaType.Keyword,
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
null);
|
||||
```
|
||||
|
||||
The index usage flag is displayed in the payload schema with the [collection info API](https://qdrant.github.io/qdrant/redoc/index.html#operation/get_collection).
|
||||
|
||||
Payload schema example:
|
||||
|
||||
@@ -143,6 +143,34 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.ValueFactory.value;
|
||||
import static io.qdrant.client.VectorsFactory.vectors;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.PointStruct;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.upsertAsync(
|
||||
"{collection_name}",
|
||||
List.of(
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(UUID.fromString("5c56c793-69f3-4fbf-87e6-c4bf54c28c26")))
|
||||
.setVectors(vectors(0.05f, 0.61f, 0.76f, 0.74f))
|
||||
.putAllPayload(Map.of("color", value("Red")))
|
||||
.build()))
|
||||
.get();
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```http
|
||||
@@ -209,6 +237,33 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.ValueFactory.value;
|
||||
import static io.qdrant.client.VectorsFactory.vectors;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.PointStruct;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.upsertAsync(
|
||||
"{collection_name}",
|
||||
List.of(
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(1))
|
||||
.setVectors(vectors(0.05f, 0.61f, 0.76f, 0.74f))
|
||||
.putAllPayload(Map.of("color", value("Red")))
|
||||
.build()))
|
||||
.get();
|
||||
```
|
||||
|
||||
are both possible.
|
||||
|
||||
## Upload points
|
||||
@@ -517,6 +572,42 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.VectorsFactory.namedVectors;
|
||||
|
||||
import io.qdrant.client.grpc.Points.PointStruct;
|
||||
|
||||
client
|
||||
.upsertAsync(
|
||||
"{collection_name}",
|
||||
List.of(
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(1))
|
||||
.setVectors(
|
||||
namedVectors(
|
||||
Map.of(
|
||||
"image",
|
||||
List.of(0.9f, 0.1f, 0.1f, 0.2f),
|
||||
"text",
|
||||
List.of(0.4f, 0.7f, 0.1f, 0.8f, 0.1f, 0.1f, 0.9f, 0.2f))))
|
||||
.build(),
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(2))
|
||||
.setVectors(
|
||||
namedVectors(
|
||||
Map.of(
|
||||
"image",
|
||||
List.of(0.2f, 0.1f, 0.3f, 0.9f),
|
||||
"text",
|
||||
List.of(0.5f, 0.2f, 0.7f, 0.4f, 0.7f, 0.2f, 0.3f, 0.9f))))
|
||||
.build()))
|
||||
.get();
|
||||
```
|
||||
|
||||
*Available as of v1.2.0*
|
||||
|
||||
Named vectors are optional. When uploading points, some vectors may be omitted.
|
||||
@@ -681,6 +772,51 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.VectorFactory.vector;
|
||||
|
||||
import io.qdrant.client.grpc.Points.NamedVectors;
|
||||
import io.qdrant.client.grpc.Points.PointStruct;
|
||||
import io.qdrant.client.grpc.Points.Vectors;
|
||||
|
||||
client
|
||||
.upsertAsync(
|
||||
"{collection_name}",
|
||||
List.of(
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(1))
|
||||
.setVectors(
|
||||
Vectors.newBuilder()
|
||||
.setVectors(
|
||||
NamedVectors.newBuilder()
|
||||
.putAllVectors(
|
||||
Map.of(
|
||||
"text", vector(List.of(1.0f, 2.0f), List.of(6, 7))))
|
||||
.build())
|
||||
.build())
|
||||
.build(),
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(2))
|
||||
.setVectors(
|
||||
Vectors.newBuilder()
|
||||
.setVectors(
|
||||
NamedVectors.newBuilder()
|
||||
.putAllVectors(
|
||||
Map.of(
|
||||
"text",
|
||||
vector(
|
||||
List.of(0.1f, 0.2f, 0.3f, 0.4f, 0.5f),
|
||||
List.of(1, 2, 3, 4, 5))))
|
||||
.build())
|
||||
.build())
|
||||
.build()))
|
||||
.get();
|
||||
```
|
||||
|
||||
## Modify points
|
||||
|
||||
To change a point, you can modify its vectors or its payload. There are several
|
||||
@@ -785,6 +921,32 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.VectorsFactory.namedVectors;
|
||||
|
||||
client
|
||||
.updateVectorsAsync(
|
||||
"{collection_name}",
|
||||
List.of(
|
||||
PointVectors.newBuilder()
|
||||
.setId(id(1))
|
||||
.setVectors(namedVectors(Map.of("image", List.of(0.1f, 0.2f, 0.3f, 0.4f))))
|
||||
.build(),
|
||||
PointVectors.newBuilder()
|
||||
.setId(id(2))
|
||||
.setVectors(
|
||||
namedVectors(
|
||||
Map.of(
|
||||
"text", List.of(0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f, 0.2f))))
|
||||
.build()))
|
||||
.get();
|
||||
```
|
||||
|
||||
|
||||
To update points and replace all of its vectors, see [uploading
|
||||
points](#upload-points).
|
||||
|
||||
@@ -844,6 +1006,17 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
|
||||
client
|
||||
.deleteVectorsAsync(
|
||||
"{collection_name}", List.of("text", "image"), List.of(id(0), id(3), id(10)))
|
||||
.get();
|
||||
```
|
||||
|
||||
To delete entire points, see [deleting points](#delete-points).
|
||||
|
||||
### Update payload
|
||||
@@ -895,6 +1068,14 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
|
||||
client.deleteAsync("{collection_name}", List.of(id(0), id(3), id(100)));
|
||||
```
|
||||
|
||||
Alternative way to specify which points to remove is to use filter.
|
||||
|
||||
```http
|
||||
@@ -963,6 +1144,18 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
|
||||
client
|
||||
.deleteAsync(
|
||||
"{collection_name}",
|
||||
Filter.newBuilder().addMust(matchKeyword("color", "red")).build())
|
||||
.get();
|
||||
```
|
||||
|
||||
This example removes all points with `{ "color": "red" }` from the collection.
|
||||
|
||||
## Retrieve points
|
||||
@@ -1004,6 +1197,16 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
|
||||
client
|
||||
.retrieveAsync("{collection_name}", List.of(id(0), id(30), id(100)), false, false, null)
|
||||
.get();
|
||||
```
|
||||
|
||||
This method has additional parameters `with_vectors` and `with_payload`.
|
||||
Using these parameters, you can select parts of the point you want as a result.
|
||||
Excluding helps you not to waste traffic transmitting useless data.
|
||||
@@ -1098,6 +1301,24 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
import static io.qdrant.client.WithPayloadSelectorFactory.enable;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||
|
||||
client
|
||||
.scrollAsync(
|
||||
ScrollPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(Filter.newBuilder().addMust(matchKeyword("color", "red")).build())
|
||||
.setLimit(1)
|
||||
.setWithPayload(enable(true))
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Returns all point with `color` = `red`.
|
||||
|
||||
```json
|
||||
@@ -1205,6 +1426,19 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
|
||||
client
|
||||
.countAsync(
|
||||
"{collection_name}",
|
||||
Filter.newBuilder().addMust(matchKeyword("color", "red")).build(),
|
||||
true)
|
||||
.get();
|
||||
```
|
||||
|
||||
Returns number of counts matching given filtering conditions:
|
||||
|
||||
```json
|
||||
|
||||
@@ -158,6 +158,32 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.SearchParams;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setFilter(Filter.newBuilder().addMust(matchKeyword("city", "London")).build())
|
||||
.setParams(SearchParams.newBuilder().setExact(false).setHnswEf(128).build())
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setLimit(3)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
In this example, we are looking for vectors similar to vector `[0.2, 0.1, 0.9, 0.7]`.
|
||||
Parameter `limit` (or its alias - `top`) specifies the amount of most similar results we would like to retrieve.
|
||||
|
||||
@@ -249,6 +275,27 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setVectorName("image")
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setLimit(3)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Search is processing only among vectors with the same name.
|
||||
|
||||
*Available as of v1.7.0*
|
||||
@@ -336,6 +383,29 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
import io.qdrant.client.grpc.Points.SparseIndices;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.setVectorName("text")
|
||||
.addAllVector(List.of(2.0f, 1.0f))
|
||||
.setSparseIndices(SparseIndices.newBuilder().addAllData(List.of(1, 7)).build())
|
||||
.setLimit(3)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
### Filtering results by score
|
||||
|
||||
In addition to payload filtering, it might be useful to filter out results with a low similarity score.
|
||||
@@ -396,6 +466,31 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.WithPayloadSelectorFactory.enable;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.WithVectorsSelectorFactory;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setWithPayload(enable(true))
|
||||
.setWithVectors(WithVectorsSelectorFactory.enable(true))
|
||||
.setLimit(3)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
You can use `with_payload` to scope to or filter a specific payload subset.
|
||||
You can even specify an array of items to include, such as `city`,
|
||||
`village`, and `town`:
|
||||
@@ -448,6 +543,29 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.WithPayloadSelectorFactory.include;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setWithPayload(include(List.of("city", "village", "town")))
|
||||
.setLimit(3)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Or use `include` or `exclude` explicitly. For example, to exclude `city`:
|
||||
|
||||
```http
|
||||
@@ -514,6 +632,29 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.WithPayloadSelectorFactory.exclude;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setWithPayload(exclude(List.of("city")))
|
||||
.setLimit(3)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
It is possible to target nested fields using a dot notation:
|
||||
- `payload.nested_field` - for a nested field
|
||||
- `payload.nested_array[].sub_field` - for projecting nested fields within an array
|
||||
@@ -667,6 +808,35 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.grpc.Points.Filter;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
Filter filter = Filter.newBuilder().addMust(matchKeyword("city", "London")).build();
|
||||
List<SearchPoints> searches =
|
||||
List.of(
|
||||
SearchPoints.newBuilder()
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setFilter(filter)
|
||||
.setLimit(3)
|
||||
.build(),
|
||||
SearchPoints.newBuilder()
|
||||
.addAllVector(List.of(0.5f, 0.3f, 0.2f, 0.3f))
|
||||
.setFilter(filter)
|
||||
.setLimit(3)
|
||||
.build());
|
||||
client.searchBatchAsync("{collection_name}", searches, null).get();
|
||||
```
|
||||
|
||||
The result of this API contains one array per search requests.
|
||||
|
||||
```json
|
||||
@@ -754,6 +924,32 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.WithPayloadSelectorFactory.enable;
|
||||
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
import io.qdrant.client.WithVectorsSelectorFactory;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setWithPayload(enable(true))
|
||||
.setWithVectors(WithVectorsSelectorFactory.enable(true))
|
||||
.setLimit(10)
|
||||
.setOffset(100)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
Is equivalent to retrieving the 11th page with 10 records per page.
|
||||
|
||||
<aside role="alert">Large offset values may cause performance issues</aside>
|
||||
@@ -883,6 +1079,23 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import io.qdrant.client.grpc.Points.SearchPointGroups;
|
||||
|
||||
client
|
||||
.searchGroupsAsync(
|
||||
SearchPointGroups.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.addAllVector(List.of(1.1f))
|
||||
.setGroupBy("document_id")
|
||||
.setLimit(4)
|
||||
.setGroupSize(2)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
The output of a ***groups*** call looks like this:
|
||||
|
||||
```json
|
||||
@@ -1033,6 +1246,33 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import static io.qdrant.client.WithPayloadSelectorFactory.include;
|
||||
import static io.qdrant.client.WithVectorsSelectorFactory.enable;
|
||||
|
||||
import io.qdrant.client.grpc.Points.SearchPointGroups;
|
||||
import io.qdrant.client.grpc.Points.WithLookup;
|
||||
|
||||
client
|
||||
.searchGroupsAsync(
|
||||
SearchPointGroups.newBuilder()
|
||||
.setCollectionName("{collection_name}")
|
||||
.addAllVector(List.of(1.0f))
|
||||
.setGroupBy("document_id")
|
||||
.setLimit(2)
|
||||
.setGroupSize(2)
|
||||
.setWithLookup(
|
||||
WithLookup.newBuilder()
|
||||
.setCollection("documents")
|
||||
.setWithPayload(include(List.of("title", "text")))
|
||||
.setWithVectors(enable(false))
|
||||
.build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
For the `with_lookup` parameter, you can also use the shorthand `with_lookup="documents"` to bring the whole payload and vector(s) without explicitly specifying it.
|
||||
|
||||
The looked up result will show up under `lookup` in each group.
|
||||
|
||||
@@ -67,6 +67,16 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?;
|
||||
client.create_snapshot("{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.createSnapshotAsync("{collection_name}").get();
|
||||
```
|
||||
|
||||
This is a synchronous operation for which a `tar` archive file will be generated into the `snapshot_path`.
|
||||
|
||||
### Delete snapshot
|
||||
@@ -103,6 +113,16 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?;
|
||||
client.delete_snapshot("{collection_name}", "{snapshot_name}").await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client.deleteSnapshotAsync("{collection_name}", "{snapshot_name}").get();
|
||||
```
|
||||
|
||||
## List snapshot
|
||||
|
||||
List of snapshots for a collection:
|
||||
@@ -135,6 +155,16 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?;
|
||||
client.list_snapshots("{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.listSnapshotAsync("{collection_name}").get();
|
||||
```
|
||||
|
||||
## Retrieve snapshot
|
||||
|
||||
<aside role="status">Only available through the REST API for the time being.</aside>
|
||||
@@ -324,6 +354,16 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?;
|
||||
client.create_full_snapshot().await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client.createFullSnapshotAsync().get();
|
||||
```
|
||||
|
||||
### Delete full storage snapshot
|
||||
|
||||
*Available as of v1.0.0*
|
||||
@@ -356,6 +396,16 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?;
|
||||
client.delete_full_snapshot("{snapshot_name}").await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client.deleteFullSnapshotAsync("{snapshot_name}").get();
|
||||
```
|
||||
|
||||
### List full storage snapshots
|
||||
|
||||
```http
|
||||
@@ -386,6 +436,16 @@ let client = QdrantClient::from_url("http://localhost:6334").build()?;
|
||||
client.list_full_snapshots().await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
|
||||
QdrantClient client =
|
||||
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
|
||||
client.listFullSnapshotAsync().get();
|
||||
```
|
||||
|
||||
### Download full storage snapshot
|
||||
|
||||
<aside role="status">Only available through the REST API for the time being.</aside>
|
||||
|
||||
@@ -104,6 +104,26 @@ client
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
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}",
|
||||
VectorParams.newBuilder()
|
||||
.setSize(768)
|
||||
.setDistance(Distance.Cosine)
|
||||
.setOnDisk(true)
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
This will create a collection with all vectors immediately stored in memmap storage.
|
||||
This is the recommended way, in case your Qdrant instance operates with fast disks and you are working with large collections.
|
||||
|
||||
@@ -186,6 +206,36 @@ 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.OptimizersConfigDiff;
|
||||
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(768)
|
||||
.setDistance(Distance.Cosine)
|
||||
.build())
|
||||
.build())
|
||||
.setOptimizersConfig(
|
||||
OptimizersConfigDiff.newBuilder().setMemmapThreshold(20000).build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
The rule of thumb to set the memmap threshold parameter is simple:
|
||||
|
||||
- if you have a balanced use scenario - set memmap threshold the same as `indexing_threshold` (default is 20000). In this case the optimizer will not make any extra runs and will optimize all thresholds at once.
|
||||
@@ -276,6 +326,38 @@ 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.HnswConfigDiff;
|
||||
import io.qdrant.client.grpc.Collections.OptimizersConfigDiff;
|
||||
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(768)
|
||||
.setDistance(Distance.Cosine)
|
||||
.build())
|
||||
.build())
|
||||
.setOptimizersConfig(
|
||||
OptimizersConfigDiff.newBuilder().setMemmapThreshold(20000).build())
|
||||
.setHnswConfig(HnswConfigDiff.newBuilder().setOnDisk(true).build())
|
||||
.build())
|
||||
.get();
|
||||
```
|
||||
|
||||
## Payload storage
|
||||
|
||||
Qdrant supports two types of payload storages: InMemory and OnDisk.
|
||||
|
||||
@@ -41,7 +41,7 @@ For using API key based authentication in Qdrant cloud see the cloud
|
||||
section.
|
||||
|
||||
The API key then needs to be present in all REST or gRPC requests to your instance.
|
||||
All official Qdrant clients for Python, Go, Rust, and .NET support the API key parameter.
|
||||
All official Qdrant clients for Python, Go, Rust, .NET and Java support the API key parameter.
|
||||
|
||||
<!---
|
||||
Examples with clients
|
||||
@@ -91,6 +91,19 @@ let client = QdrantClient::from_url("https://xyz-example.eu-central.aws.cloud.qd
|
||||
.build()?;
|
||||
```
|
||||
|
||||
```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("<paste-your-api-key-here>")
|
||||
.build());
|
||||
```
|
||||
<aside role="alert">Internal communication channels are <strong>never</strong> protected by an API key. Internal gRPC uses port 6335 by default if running in distributed mode. You must ensure that this port is not publicly reachable and can only be used for node communication. By default, this setting is disabled for Qdrant Cloud and the Qdrant Helm chart.</aside>
|
||||
|
||||
### Read-only API key
|
||||
|
||||
@@ -17,6 +17,7 @@ or [protobuf](https://github.com/qdrant/qdrant/tree/master/lib/api/src/grpc/prot
|
||||
||**[Rust](https://github.com/qdrant/rust-client)**|`cargo add qdrant-client`|**Latest Release**|
|
||||
||**[Go](https://github.com/qdrant/go-client)**|`go get github.com/qdrant/go-client`|**Latest Release**|
|
||||
||**[.NET](https://github.com/qdrant/qdrant-dotnet)**|`dotnet add package Qdrant.Client`|**Latest Release**|
|
||||
||**[Java](https://github.com/qdrant/java-client)**|[Available on Maven Central](https://central.sonatype.com/artifact/io.qdrant/client)|**Latest Release**|
|
||||
|
||||
|
||||
## API Reference
|
||||
|
||||
@@ -54,6 +54,14 @@ use qdrant_client::client::QdrantClient;
|
||||
let client = QdrantClient::from_url("http://localhost:6334").build()?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.QdrantClient;
|
||||
import io.qdrant.client.QdrantGrpcClient;
|
||||
|
||||
QdrantClient client = new QdrantClient(
|
||||
QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||
```
|
||||
|
||||
<aside role="status">By default, Qdrant starts with no encryption or authentication . This means anyone with network access to your machine can access your Qdrant container instance. Please read <a href="https://qdrant.tech/documentation/security/">Security</a> carefully for details on how to secure your instance.</aside>
|
||||
|
||||
## Create a collection
|
||||
@@ -92,7 +100,17 @@ client
|
||||
})
|
||||
.await?;
|
||||
```
|
||||
|
||||
```java
|
||||
import io.qdrant.client.grpc.Collections.Distance;
|
||||
import io.qdrant.client.grpc.Collections.VectorParams;
|
||||
|
||||
client.createCollectionAsync("test_collection",
|
||||
VectorParams.newBuilder().setDistance(Distance.Dot).setSize(4).build()).get();
|
||||
```
|
||||
|
||||
<aside role="status">TypeScript, Rust examples use async/await syntax, so should be used in an async block.</aside>
|
||||
<aside role="status">Java examples are enclosed within a try/catch block.</aside>
|
||||
|
||||
## Add vectors
|
||||
|
||||
@@ -164,6 +182,44 @@ let operation_info = client
|
||||
|
||||
dbg!(operation_info);
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.qdrant.client.PointIdFactory.id;
|
||||
import static io.qdrant.client.ValueFactory.value;
|
||||
import static io.qdrant.client.VectorsFactory.vectors;
|
||||
|
||||
import io.qdrant.client.grpc.Points.PointStruct;
|
||||
import io.qdrant.client.grpc.Points.UpdateResult;
|
||||
|
||||
UpdateResult operationInfo =
|
||||
client
|
||||
.upsertAsync(
|
||||
"test_collection",
|
||||
List.of(
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(1))
|
||||
.setVectors(vectors(0.05f, 0.61f, 0.76f, 0.74f))
|
||||
.putAllPayload(Map.of("city", value("Berlin")))
|
||||
.build(),
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(2))
|
||||
.setVectors(vectors(0.19f, 0.81f, 0.75f, 0.11f))
|
||||
.putAllPayload(Map.of("city", value("London")))
|
||||
.build(),
|
||||
PointStruct.newBuilder()
|
||||
.setId(id(3))
|
||||
.setVectors(vectors(0.36f, 0.55f, 0.47f, 0.94f))
|
||||
.putAllPayload(Map.of("city", value("Moscow")))
|
||||
.build()))
|
||||
// Truncated
|
||||
.get();
|
||||
|
||||
System.out.println(operationInfo);
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```python
|
||||
@@ -184,6 +240,11 @@ PointsOperationResponse {
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
operation_id: 0
|
||||
status: Completed
|
||||
```
|
||||
|
||||
## Run a query
|
||||
Let's ask a basic question - Which of our stored vectors are most similar to the query vector `[0.2, 0.1, 0.9, 0.7]`?
|
||||
|
||||
@@ -220,6 +281,28 @@ let search_result = client
|
||||
dbg!(search_result);
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.List;
|
||||
|
||||
import io.qdrant.client.grpc.Points.ScoredPoint;
|
||||
import io.qdrant.client.grpc.Points.SearchPoints;
|
||||
|
||||
import static io.qdrant.client.WithPayloadSelectorFactory.enable;
|
||||
|
||||
List<ScoredPoint> searchResult =
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("test_collection")
|
||||
.setLimit(3)
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setWithPayload(enable(true))
|
||||
.build())
|
||||
.get();
|
||||
|
||||
System.out.println(searchResult);
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```python
|
||||
@@ -289,6 +372,43 @@ SearchResponse {
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
[id {
|
||||
num: 4
|
||||
}
|
||||
payload {
|
||||
key: "city"
|
||||
value {
|
||||
string_value: "New York"
|
||||
}
|
||||
}
|
||||
score: 1.362
|
||||
version: 1
|
||||
, id {
|
||||
num: 1
|
||||
}
|
||||
payload {
|
||||
key: "city"
|
||||
value {
|
||||
string_value: "Berlin"
|
||||
}
|
||||
}
|
||||
score: 1.273
|
||||
version: 1
|
||||
, id {
|
||||
num: 3
|
||||
}
|
||||
payload {
|
||||
key: "city"
|
||||
value {
|
||||
string_value: "Moscow"
|
||||
}
|
||||
}
|
||||
score: 1.208
|
||||
version: 1
|
||||
]
|
||||
```
|
||||
|
||||
The results are returned in decreasing similarity order. Note that payload and vector data is missing in these results by default.
|
||||
See [payload and vector in the result](../concepts/search#payload-and-vector-in-the-result) on how to enable it.
|
||||
|
||||
@@ -344,6 +464,24 @@ let search_result = client
|
||||
dbg!(search_result);
|
||||
```
|
||||
|
||||
```java
|
||||
import static io.qdrant.client.ConditionFactory.matchKeyword;
|
||||
|
||||
List<ScoredPoint> searchResult =
|
||||
client
|
||||
.searchAsync(
|
||||
SearchPoints.newBuilder()
|
||||
.setCollectionName("test_collection")
|
||||
.setLimit(3)
|
||||
.setFilter(Filter.newBuilder().addMust(matchKeyword("city", "London")))
|
||||
.addAllVector(List.of(0.2f, 0.1f, 0.9f, 0.7f))
|
||||
.setWithPayload(enable(true))
|
||||
.build())
|
||||
.get();
|
||||
|
||||
System.out.println(searchResult);
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```python
|
||||
@@ -393,6 +531,21 @@ SearchResponse {
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
[id {
|
||||
num: 2
|
||||
}
|
||||
payload {
|
||||
key: "city"
|
||||
value {
|
||||
string_value: "London"
|
||||
}
|
||||
}
|
||||
score: 0.871
|
||||
version: 1
|
||||
]
|
||||
```
|
||||
|
||||
<aside role="status">To make filtered search fast on real datasets, we highly recommend to create <a href="../concepts/indexing/#payload-index">payload indexes</a>!</aside>
|
||||
|
||||
You have just conducted vector search. You loaded vectors into a database and queried the database with a vector of your own. Qdrant found the closest results and presented you with a similarity score.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
Reference in New Issue
Block a user