docs: Added Rust client usage (#401)

* docs: Rust quick-start

* docs: rust auth.md

* docs: Rust /collections usage

* docs: filtering Rust

* docs: filtering Rust

* docs: Rust /indexing

* docs: Rust /payload

* docs: Rust /points

* docs: Rust /storage

* docs: Rust /snapshots

* docs: Rust /search

* New line after code blocks

* Add Rust imports

* Functions end with semicolon, values end without it

* Reformat using rustfmt

* Use TokenizerType ID from type

* Define score as Rust let if

* Add example of update collection call, implemented in Rust client 1.7.0

* chore: hide update_collection()

---------

Co-authored-by: timvisee <tim@visee.me>
This commit is contained in:
Anush
2023-11-20 13:50:28 +01:00
committed by GitHub
co-authored by timvisee
parent 3f8606eae9
commit 756879705e
10 changed files with 1812 additions and 24 deletions
@@ -131,6 +131,33 @@ client.search("{collection_name}", {
});
```
```rust
use qdrant_client::{
client::QdrantClient,
qdrant::{Condition, Filter, SearchParams, SearchPoints},
};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
client
.search_points(&SearchPoints {
collection_name: "{collection_name}".to_string(),
filter: Some(Filter::must([Condition::matches(
"city",
"London".to_string(),
)])),
params: Some(SearchParams {
hnsw_ef: Some(128),
exact: Some(false),
..Default::default()
}),
vector: vec![0.2, 0.1, 0.9, 0.7],
limit: 3,
..Default::default()
})
.await?;
```
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.
@@ -207,6 +234,22 @@ client.search("{collection_name}", {
});
```
```rust
use qdrant_client::{client::QdrantClient, qdrant::SearchPoints};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
client
.search_points(&SearchPoints {
collection_name: "{collection_name}".to_string(),
vector: vec![0.2, 0.1, 0.9, 0.7],
vector_name: Some("image".to_string()),
limit: 3,
..Default::default()
})
.await?;
```
Search is processing only among vectors with the same name.
### Filtering results by score
@@ -253,6 +296,23 @@ client.search("{collection_name}", {
});
```
```rust
use qdrant_client::{client::QdrantClient, qdrant::SearchPoints};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
client
.search_points(&SearchPoints {
collection_name: "{collection_name}".to_string(),
vector: vec![0.2, 0.1, 0.9, 0.7],
with_payload: Some(true.into()),
with_vectors: Some(true.into()),
limit: 3,
..Default::default()
})
.await?;
```
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`:
@@ -290,6 +350,22 @@ client.search("{collection_name}", {
});
```
```rust
use qdrant_client::{client::QdrantClient, qdrant::SearchPoints};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
client
.search_points(&SearchPoints {
collection_name: "{collection_name}".to_string(),
vector: vec![0.2, 0.1, 0.9, 0.7],
with_payload: Some(vec!["city", "village", "town"].into()),
limit: 3,
..Default::default()
})
.await?;
```
Or use `include` or `exclude` explicitly. For example, to exclude `city`:
```http
@@ -331,6 +407,32 @@ client.search("{collection_name}", {
});
```
```rust
use qdrant_client::{
client::QdrantClient,
qdrant::{
with_payload_selector::SelectorOptions, PayloadIncludeSelector, SearchPoints,
WithPayloadSelector,
},
};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
client
.search_points(&SearchPoints {
collection_name: "{collection_name}".to_string(),
vector: vec![0.2, 0.1, 0.9, 0.7],
with_payload: Some(WithPayloadSelector {
selector_options: Some(SelectorOptions::Include(PayloadIncludeSelector {
fields: vec!["city".to_string()],
})),
}),
limit: 3,
..Default::default()
})
.await?;
```
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
@@ -449,6 +551,42 @@ client.searchBatch("{collection_name}", {
});
```
```rust
use qdrant_client::{
client::QdrantClient,
qdrant::{Condition, Filter, SearchBatchPoints, SearchPoints},
};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
let filter = Filter::must([Condition::matches("city", "London".to_string())]);
let searches = vec![
SearchPoints {
collection_name: "{collection_name}".to_string(),
vector: vec![0.2, 0.1, 0.9, 0.7],
filter: Some(filter.clone()),
limit: 3,
..Default::default()
},
SearchPoints {
collection_name: "{collection_name}".to_string(),
vector: vec![0.5, 0.3, 0.2, 0.3],
filter: Some(filter),
limit: 3,
..Default::default()
},
];
client
.search_batch_points(&SearchBatchPoints {
collection_name: "{collection_name}".to_string(),
search_points: searches,
read_consistency: None,
})
.await?;
```
The result of this API contains one array per search requests.
```json
@@ -544,6 +682,32 @@ client.recommend("{collection_name}", {
});
```
```rust
use qdrant_client::{
client::QdrantClient,
qdrant::{Condition, Filter, RecommendPoints, RecommendStrategy},
};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
client
.recommend(&RecommendPoints {
collection_name: "{collection_name}".to_string(),
positive: vec![100.into(), 200.into()],
positive_vectors: vec![vec![100.0, 231.0].into()],
negative: vec![718.into()],
negative_vectors: vec![vec![0.2, 0.3, 0.4, 0.5].into()],
strategy: Some(RecommendStrategy::AverageVector.into()),
filter: Some(Filter::must([Condition::matches(
"city",
"London".to_string(),
)])),
limit: 3,
..Default::default()
})
.await?;
```
Example result of this API would be
```json
@@ -582,11 +746,11 @@ A new strategy introduced in v1.6, is called `best_score`. It is based on the id
The way it works is that each candidate is measured against every example, then we select the best positive and best negative scores. The final score is chosen with this step formula:
```rust
if best_positive_score > best_negative_score {
score = best_positive_score
let score = if best_positive_score > best_negative_score {
best_positive_score;
} else {
score = -(best_negative_score * best_negative_score)
}
-(best_negative_score * best_negative_score);
};
```
<aside role="alert">The performance of `best_score` strategy will be linearly impacted by the amount of examples.</aside>
@@ -637,6 +801,21 @@ client.recommend("{collection_name}", {
});
```
```rust
use qdrant_client::qdrant::RecommendPoints;
client
.recommend(&RecommendPoints {
collection_name: "{collection_name}".to_string(),
positive: vec![100.into(), 231.into()],
negative: vec![718.into()],
using: Some("image".to_string()),
limit: 10,
..Default::default()
})
.await?;
```
Parameter `using` specifies which stored vectors to use for the recommendation.
## Batch recommendation API
@@ -746,6 +925,44 @@ client.recommend_batch("{collection_name}", {
});
```
```rust
use qdrant_client::{
client::QdrantClient,
qdrant::{Condition, Filter, RecommendBatchPoints, RecommendPoints},
};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
let filter = Filter::must([Condition::matches("city", "London".to_string())]);
let recommend_queries = vec![
RecommendPoints {
collection_name: "{collection_name}".to_string(),
positive: vec![100.into(), 231.into()],
negative: vec![718.into()],
filter: Some(filter.clone()),
limit: 3,
..Default::default()
},
RecommendPoints {
collection_name: "{collection_name}".to_string(),
positive: vec![200.into(), 67.into()],
negative: vec![300.into()],
filter: Some(filter),
limit: 3,
..Default::default()
},
];
client
.recommend_batch(&RecommendBatchPoints {
collection_name: "{collection_name}".to_string(),
recommend_points: recommend_queries,
..Default::default()
})
.await?;
```
The result of this API contains one array per recommendation requests.
```json
@@ -816,6 +1033,24 @@ client.search("{collection_name}", {
});
```
```rust
use qdrant_client::{client::QdrantClient, qdrant::SearchPoints};
let client = QdrantClient::from_url("http://localhost:6334").build()?;
client
.search_points(&SearchPoints {
collection_name: "{collection_name}".to_string(),
vector: vec![0.2, 0.1, 0.9, 0.7],
with_vectors: Some(true.into()),
with_payload: Some(true.into()),
limit: 10,
offset: Some(100),
..Default::default()
})
.await?;
```
Is equivalent to retrieving the 11th page with 10 records per page.
<aside role="alert">Large offset values may cause performance issues</aside>
@@ -914,7 +1149,7 @@ POST /collections/{collection_name}/points/search/groups
client.search_groups(
collection_name="{collection_name}",
# Same as in the regular search() API
query_vector=[1.1],
query_vector=g,
# Grouping parameters
group_by="document_id", # Path of the field to group by
limit=4, # Max amount of groups
@@ -931,6 +1166,21 @@ client.searchPointGroups("{collection_name}", {
});
```
```rust
use qdrant_client::qdrant::SearchPointGroups;
client
.search_groups(&SearchPointGroups {
collection_name: "{collection_name}".to_string(),
vector: vec![1.1],
group_by: "document_id".to_string(),
limit: 4,
group_size: 2,
..Default::default()
})
.await?;
```
### Recommend groups
REST API ([Schema](https://qdrant.github.io/qdrant/redoc/index.html#tag/points/operation/recommend_point_groups)):
@@ -973,6 +1223,22 @@ client.recommendPointGroups("{collection_name}", {
});
```
```rust
use qdrant_client::qdrant::RecommendPointGroups;
client
.recommend_groups(&RecommendPointGroups {
collection_name: "{collection_name}".to_string(),
positive: vec![1.into()],
negative: vec![2.into(), 5.into()],
group_by: "document_id".to_string(),
limit: 4,
group_size: 10,
..Default::default()
})
.await?;
```
In either case (search or recommend), the output would look like this:
```json
@@ -983,13 +1249,13 @@ In either case (search or recommend), the output would look like this:
"id": "a",
"hits": [
{ "id": 0, "score": 0.91 },
{ "id": 1, "score": 0.85 },
{ "id": 1, "score": 0.85 }
]
},
{
"id": "b",
"hits": [
{ "id": 1, "score": 0.85 },
{ "id": 1, "score": 0.85 }
]
},
{
@@ -1097,13 +1363,33 @@ client.searchPointGroups("{collection_name}", {
limit: 2,
group_size: 2,
with_lookup: {
collection: "documents",
collection: w,
with_payload: ["title", "text"],
with_vectors: false,
},
});
```
```rust
use qdrant_client::qdrant::{SearchPointGroups, WithLookup};
client
.search_groups(&SearchPointGroups {
collection_name: "{collection_name}".to_string(),
vector: vec![1.1],
group_by: "document_id".to_string(),
limit: 2,
group_size: 2,
with_lookup: Some(WithLookup {
collection: "documents".to_string(),
with_payload: Some(vec!["title", "text"].into()),
with_vectors: Some(false.into()),
}),
..Default::default()
})
.await?;
```
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.