From 756879705e275205f036f5db0960f9524e759328 Mon Sep 17 00:00:00 2001 From: Anush Date: Mon, 20 Nov 2023 18:20:28 +0530 Subject: [PATCH] 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 --- .../documentation/cloud/authentication.md | 11 +- .../documentation/concepts/collections.md | 204 ++++++- .../documentation/concepts/filtering.md | 335 ++++++++++++ .../documentation/concepts/indexing.md | 45 ++ .../content/documentation/concepts/payload.md | 119 ++++- .../content/documentation/concepts/points.md | 504 +++++++++++++++++- .../content/documentation/concepts/search.md | 302 ++++++++++- .../documentation/concepts/snapshots.md | 48 ++ .../content/documentation/concepts/storage.md | 88 +++ .../content/documentation/quick-start.md | 180 ++++++- 10 files changed, 1812 insertions(+), 24 deletions(-) diff --git a/qdrant-landing/content/documentation/cloud/authentication.md b/qdrant-landing/content/documentation/cloud/authentication.md index 0ca6d7bc4..cebb57c81 100644 --- a/qdrant-landing/content/documentation/cloud/authentication.md +++ b/qdrant-landing/content/documentation/cloud/authentication.md @@ -55,4 +55,13 @@ var client = new QdrantClient( https: true, apiKey: "" ); -``` \ No newline at end of file +``` + +```rust +use qdrant_client::client::QdrantClient; + +let client = QdrantClient::from_url("xyz-example.eu-central.aws.cloud.qdrant.io:6334") + .with_api_key("") + .build() + .unwrap(); +``` diff --git a/qdrant-landing/content/documentation/concepts/collections.md b/qdrant-landing/content/documentation/concepts/collections.md index 1e7d7ba8f..a63032578 100644 --- a/qdrant-landing/content/documentation/concepts/collections.md +++ b/qdrant-landing/content/documentation/concepts/collections.md @@ -64,6 +64,30 @@ client.createCollection("{collection_name}", { }); ``` +```rust +use qdrant_client::{ + client::QdrantClient, + qdrant::{vectors_config::Config, CreateCollection, Distance, VectorParams, VectorsConfig}, +}; + +//The Rust client uses Qdrant's GRPC interface +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client + .create_collection(&CreateCollection { + collection_name: "{collection_name}".to_string(), + vectors_config: Some(VectorsConfig { + config: Some(Config::Params(VectorParams { + size: 100, + distance: Distance::Cosine.into(), + ..Default::default() + })), + }), + ..Default::default() + }) + .await?; +``` + 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. @@ -100,7 +124,7 @@ PUT /collections/{collection_name} { "vectors": { - "size": 300, + "size": 100, "distance": "Cosine" }, "init_from": { @@ -133,6 +157,30 @@ client.createCollection("{collection_name}", { }); ``` +```rust +use qdrant_client::{ + client::QdrantClient, + qdrant::{vectors_config::Config, CreateCollection, Distance, VectorParams, VectorsConfig}, +}; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client + .create_collection(&CreateCollection { + collection_name: "{collection_name}".to_string(), + vectors_config: Some(VectorsConfig { + config: Some(Config::Params(VectorParams { + size: 100, + distance: Distance::Cosine.into(), + ..Default::default() + })), + }), + init_from_collection: Some("{from_collection_name}".to_string()), + ..Default::default() + }) + .await?; +``` + ### Collection with multiple vectors *Available as of v0.10.0* @@ -187,6 +235,48 @@ client.createCollection("{collection_name}", { }); ``` +```rust +use qdrant_client::{ + client::QdrantClient, + qdrant::{ + vectors_config::Config, CreateCollection, Distance, VectorParams, VectorParamsMap, + VectorsConfig, + }, +}; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client + .create_collection(&CreateCollection { + collection_name: "{collection_name}".to_string(), + vectors_config: Some(VectorsConfig { + config: Some(Config::ParamsMap(VectorParamsMap { + map: [ + ( + "image".to_string(), + VectorParams { + size: 4, + distance: Distance::Dot.into(), + ..Default::default() + }, + ), + ( + "text".to_string(), + VectorParams { + size: 8, + distance: Distance::Cosine.into(), + ..Default::default() + }, + ), + ] + .into(), + })), + }), + ..Default::default() + }) + .await?; +``` + For rare use cases, it is possible to create a collection without any vector storage. *Available as of v1.1.1* @@ -219,6 +309,10 @@ client.delete_collection(collection_name="{collection_name}") client.deleteCollection("{collection_name}"); ``` +```rust +client.delete_collection("{collection_name}").await?; +``` + ### Update collection parameters Dynamic parameter updates may be helpful, for example, for more efficient initial loading of vectors. @@ -252,6 +346,20 @@ client.updateCollection("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::OptimizersConfigDiff; + +client + .update_collection( + "{collection_name}", + &OptimizersConfigDiff { + indexing_threshold: Some(10000), + ..Default::default() + }, + ) + .await?; +``` + The following parameters can be updated: * `optimizers_config` - see [optimizer](../optimizer/) for details. @@ -402,6 +510,57 @@ client.updateCollection("{collection_name}", { }); ``` + + ## Collection info Qdrant allows determining the configuration parameters of an existing collection to better understand how the points are @@ -465,6 +624,10 @@ client.get_collection(collection_name="{collection_name}") client.getCollection("{collection_name}"); ``` +```rust +client.collection_info("{collection_name}").await?; +``` + 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. @@ -544,6 +707,10 @@ client.updateCollectionAliases({ }); ``` +```rust +client.create_alias("example_collection", "production_collection").await?; +``` + ### Remove alias ```http @@ -582,6 +749,10 @@ client.updateCollectionAliases({ }); ``` +```rust +client.delete_alias("production_collection").await?; +``` + ### Switch collection Multiple alias actions are performed atomically. @@ -640,6 +811,11 @@ client.updateCollectionAliases({ }); ``` +```rust +client.delete_alias("production_collection").await?; +client.create_alias("example_collection", "production_collection").await?; +``` + ### List collection aliases ```http @@ -662,6 +838,14 @@ const client = new QdrantClient({ host: "localhost", port: 6333 }); client.getCollectionAliases("{collection_name}"); ``` +```rust +use qdrant_client::client::QdrantClient; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client.list_collection_aliases("{collection_name}").await?; +``` + ### List all aliases ```http @@ -684,6 +868,14 @@ const client = new QdrantClient({ host: "localhost", port: 6333 }); client.getAliases(); ``` +```rust +use qdrant_client::client::QdrantClient; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client.list_aliases().await?; +``` + ### List all collections ```http @@ -704,4 +896,12 @@ import { QdrantClient } from "@qdrant/js-client-rest"; const client = new QdrantClient({ host: "localhost", port: 6333 }); client.getCollections(); -``` \ No newline at end of file +``` + +```rust +use qdrant_client::client::QdrantClient; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client.list_collections().await?; +``` diff --git a/qdrant-landing/content/documentation/concepts/filtering.md b/qdrant-landing/content/documentation/concepts/filtering.md index b44182bf4..98ab3d195 100644 --- a/qdrant-landing/content/documentation/concepts/filtering.md +++ b/qdrant-landing/content/documentation/concepts/filtering.md @@ -96,6 +96,26 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::{ + client::QdrantClient, + qdrant::{Condition, Filter, ScrollPoints}, +}; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client + .scroll(&ScrollPoints { + collection_name: "test_collection".to_string(), + filter: Some(Filter::must([ + Condition::matches("city", "london".to_string()), + Condition::matches("color", "red".to_string()), + ])), + ..Default::default() + }) + .await?; +``` + Filtered points would be: ```json @@ -157,6 +177,21 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "test_collection".to_string(), + filter: Some(Filter::should([ + Condition::matches("city", "london".to_string()), + Condition::matches("color", "red".to_string()), + ])), + ..Default::default() + }) + .await?; +``` + Filtered points would be: ```json @@ -217,6 +252,21 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "test_collection".to_string(), + filter: Some(Filter::must_not([ + Condition::matches("city", "london".to_string()), + Condition::matches("color", "red".to_string()), + ])), + ..Default::default() + }) + .await?; +``` + Filtered points would be: ```json @@ -281,6 +331,22 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "{collection_name}".to_string(), + filter: Some(Filter { + must: vec![Condition::matches("city", "London".to_string())], + must_not: vec![Condition::matches("color", "red".to_string())], + ..Default::default() + }), + ..Default::default() + }) + .await?; +``` + Filtered points would be: ```json @@ -352,6 +418,22 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "{collection_name}".to_string(), + filter: Some(Filter::must_not([Filter::must([ + Condition::matches("city", "London".to_string()), + Condition::matches("color", "Red".to_string()), + ]) + .into()])), + ..Default::default() + }) + .await?; +``` + Filtered points would be: ```json @@ -394,6 +476,10 @@ models.FieldCondition( } ``` +```rust +Condition::matches("color", "red".to_string()) +``` + For the other types, the match condition will look exactly the same, except for the type used: ```json @@ -419,6 +505,10 @@ models.FieldCondition( } ``` +```rust +Condition::matches("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. @@ -457,6 +547,10 @@ FieldCondition( } ``` +```rust +Condition::matches("color", vec!["black".to_string(), "yellow".to_string()]) +``` + 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"]`. @@ -497,6 +591,13 @@ FieldCondition( } ``` +```rust +Condition::matches( + "color", + !MatchValue::from(vec!["black".to_string(), "yellow".to_string()]), +) +``` + 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"`. @@ -597,6 +698,21 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "{collection_name}".to_string(), + filter: Some(Filter::should([Condition::matches( + "country.name", + "Germany".to_string(), + )])), + ..Default::default() + }) + .await?; +``` + You can also search through arrays by projecting inner values using the `[]` syntax. ```http @@ -653,6 +769,24 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, Range, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "{collection_name}".to_string(), + filter: Some(Filter::should([Condition::range( + "country.cities[].population", + Range { + gte: Some(9.0), + ..Default::default() + }, + )])), + ..Default::default() + }) + .await?; +``` + 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. @@ -701,6 +835,21 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "{collection_name}".to_string(), + filter: Some(Filter::should([Condition::matches( + "country.cities[].sightseeing", + "Osaka Castle".to_string(), + )])), + ..Default::default() + }) + .await?; +``` + 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 @@ -790,6 +939,21 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "test_collection".to_string(), + filter: Some(Filter::must([ + Condition::matches("diet[].food", "meat".to_string()), + Condition::matches("diet[].likes", true), + ])), + ..Default::default() + }) + .await?; +``` + 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` @@ -886,6 +1050,25 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, NestedCondition, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "{collection_name}".to_string(), + filter: Some(Filter::must([NestedCondition { + key: "diet".to_string(), + filter: Some(Filter::must([ + Condition::matches("food", "meat".to_string()), + Condition::matches("likes", true), + ])), + } + .into()])), + ..Default::default() + }) + .await?; +``` + 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. @@ -983,6 +1166,28 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, NestedCondition, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "{collection_name}".to_string(), + filter: Some(Filter::must([ + NestedCondition { + key: "diet".to_string(), + filter: Some(Filter::must([ + Condition::matches("food", "meat".to_string()), + Condition::matches("likes", true), + ])), + } + .into(), + Condition::has_id([1]), + ])), + ..Default::default() + }) + .await?; +``` + ### Full Text Match *Available as of v0.10.0* @@ -1018,6 +1223,12 @@ models.FieldCondition( } ``` +```rust +// If the match string contains a white-space, full text match is performed. +// Otherwise a keyword match is performed. +Condition::matches("description", "good cheap".to_string()) +``` + If the query has several words, then the condition will be satisfied only if all of them are present in the text. ### Range @@ -1058,6 +1269,18 @@ models.FieldCondition( } ``` +```rust +Condition::range( + "price", + Range { + gt: None, + gte: Some(100.0), + lt: None, + lte: Some(450.0), + }, +) +``` + 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. @@ -1122,6 +1345,22 @@ models.FieldCondition( } ``` +```rust +Condition::geo_bounding_box( + "location", + GeoBoundingBox { + bottom_right: Some(GeoPoint { + lon: 13.455868, + lat: 52.495862, + }), + top_left: Some(GeoPoint { + lon: 13.403683, + lat: 52.520711, + }), + }, +) +``` + 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 @@ -1165,6 +1404,19 @@ models.FieldCondition( } ``` +```rust +Condition::geo_radius( + "location", + GeoRadius { + center: Some(GeoPoint { + lon: 13.403683, + lat: 52.520711, + }), + radius: 1000.0, + }, +) +``` + 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. @@ -1320,6 +1572,59 @@ models.FieldCondition( } ``` +```rust +Condition::geo_polygon( + "location", + GeoPolygon { + exterior: Some(GeoLineString { + points: vec![ + GeoPoint { + lon: -70.0, + lat: -70.0, + }, + GeoPoint { + lon: 60.0, + lat: -70.0, + }, + GeoPoint { + lon: 60.0, + lat: 60.0, + }, + GeoPoint { + lon: -70.0, + lat: 60.0, + }, + GeoPoint { + lon: -70.0, + lat: -70.0, + }, + ], + }), + interiors: vec![GeoLineString { + points: vec![ + GeoPoint { + lon: -65.0, + lat: -65.0, + }, + GeoPoint { + lon: 0.0, + lat: -65.0, + }, + GeoPoint { lon: 0.0, lat: 0.0 }, + GeoPoint { + lon: -65.0, + lat: 0.0, + }, + GeoPoint { + lon: -65.0, + lat: -65.0, + }, + ], + }], + }, +) +``` + 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. @@ -1363,6 +1668,16 @@ models.FieldCondition( } ``` +```rust +Condition::values_count( + "comments", + ValuesCount { + gt: Some(2), + ..Default::default() + }, +) +``` + The result would be: ```json @@ -1398,6 +1713,10 @@ models.IsEmptyCondition( } ``` +```rust +Condition::is_empty("reports") +``` + This condition will match all records where the field `reports` either does not exist, or has `null` or `[]` value. @@ -1429,6 +1748,10 @@ models.IsNullCondition( } ``` +```rust +Condition::is_null("reports") +``` + This condition will match all records where the field `reports` exists and has `NULL` value. @@ -1473,6 +1796,18 @@ client.scroll("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{Condition, Filter, ScrollPoints}; + +client + .scroll(&ScrollPoints { + collection_name: "{collection_name}".to_string(), + filter: Some(Filter::must([Condition::has_id([1, 3, 5, 7, 9, 11])])), + ..Default::default() + }) + .await?; +``` + Filtered points would be: ```json diff --git a/qdrant-landing/content/documentation/concepts/indexing.md b/qdrant-landing/content/documentation/concepts/indexing.md index 48c965b62..cc125ca74 100644 --- a/qdrant-landing/content/documentation/concepts/indexing.md +++ b/qdrant-landing/content/documentation/concepts/indexing.md @@ -57,6 +57,22 @@ client.createPayloadIndex("{collection_name}", { }); ``` +```rust +use qdrant_client::{client::QdrantClient, qdrant::FieldType}; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client + .create_field_index( + "{collection_name}", + "name_of_the_field_to_index", + FieldType::Keyword, + None, + None, + ) + .await?; +``` + Available field types are: * `keyword` - for [keyword](../payload/#keyword) payload, affects [Match](../filtering/#match) filtering conditions. @@ -133,6 +149,35 @@ client.createPayloadIndex("{collection_name}", { }); ``` +```rust +use qdrant_client::{ + client::QdrantClient, + qdrant::{ + payload_index_params::IndexParams, FieldType, PayloadIndexParams, TextIndexParams, + TokenizerType, + }, +}; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client + .create_field_index( + "{collection_name}", + "name_of_the_field_to_index", + FieldType::Text, + Some(&PayloadIndexParams { + index_params: Some(IndexParams::TextIndexParams(TextIndexParams { + tokenizer: TokenizerType::Word as i32, + min_token_len: Some(2), + max_token_len: Some(10), + lowercase: Some(true), + })), + }), + None, + ) + .await?; +``` + Available tokenizers are: * `word` - splits the string into words, separated by spaces, punctuation marks, and special characters. diff --git a/qdrant-landing/content/documentation/concepts/payload.md b/qdrant-landing/content/documentation/concepts/payload.md index e44e69ad9..9b370cef8 100644 --- a/qdrant-landing/content/documentation/concepts/payload.md +++ b/qdrant-landing/content/documentation/concepts/payload.md @@ -236,6 +236,47 @@ client.upsert("{collection_name}", { }); ``` +```rust +use qdrant_client::{client::QdrantClient, qdrant::PointStruct}; +use serde_json::json; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +let points = vec![ + PointStruct::new( + 1, + vec![0.05, 0.61, 0.76, 0.74], + json!( + {"city": "Berlin", "price": 1.99} + ) + .try_into() + .unwrap(), + ), + PointStruct::new( + 2, + vec![0.19, 0.81, 0.75, 0.11], + json!( + {"city": ["Berlin", "London"]} + ) + .try_into() + .unwrap(), + ), + PointStruct::new( + 3, + vec![0.36, 0.55, 0.47, 0.94], + json!( + {"city": ["Berlin", "Moscow"], "price": [1.99, 2.99]} + ) + .try_into() + .unwrap(), + ), +]; + +client + .upsert_points("{collection_name}".to_string(), points, None) + .await?; +``` + ## Update payload ### Set payload @@ -277,6 +318,31 @@ client.setPayload("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{ + points_selector::PointsSelectorOneOf, PointsIdsList, PointsSelector, +}; +use serde_json::json; + +client + .set_payload( + "{collection_name}", + &PointsSelector { + points_selector_one_of: Some(PointsSelectorOneOf::Points(PointsIdsList { + ids: vec![0.into(), 3.into(), 10.into()], + })), + }, + json!({ + "property1": "string", + "property2": "string", + }) + .try_into() + .unwrap(), + None, + ) + .await?; +``` + ### Delete payload This method removes specified payload keys from specified points @@ -303,10 +369,29 @@ client.delete_payload( ```typescript client.deletePayload("{collection_name}", { keys: ["color", "price"], - points: [0, 3, 10], + points: [0, 3, 100], }); ``` +```rust +use qdrant_client::qdrant::{ + points_selector::PointsSelectorOneOf, PointsIdsList, PointsSelector, +}; + +client + .delete_payload( + "{collection_name}", + &PointsSelector { + points_selector_one_of: Some(PointsSelectorOneOf::Points(PointsIdsList { + ids: vec![0.into(), 3.into(), 100.into()], + })), + }, + vec!["color".to_string(), "price".to_string()], + None, + ) + .await?; +``` + ### Clear payload This method removes all payload keys from specified points @@ -336,6 +421,24 @@ client.clearPayload("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::{ + points_selector::PointsSelectorOneOf, PointsIdsList, PointsSelector, +}; + +client + .clear_payload( + "{collection_name}", + Some(PointsSelector { + points_selector_one_of: Some(PointsSelectorOneOf::Points(PointsIdsList { + ids: vec![0.into(), 3.into(), 100.into()], + })), + }), + None, + ) + .await?; +``` + ## Payload indexing @@ -377,6 +480,20 @@ client.createPayloadIndex("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::FieldType; + +client + .create_field_index( + "{collection_name}", + "name_of_the_field_to_index", + FieldType::Keyword, + None, + None, + ) + .await?; +``` + 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: diff --git a/qdrant-landing/content/documentation/concepts/points.md b/qdrant-landing/content/documentation/concepts/points.md index 43b2274ec..03cd26149 100755 --- a/qdrant-landing/content/documentation/concepts/points.md +++ b/qdrant-landing/content/documentation/concepts/points.md @@ -120,6 +120,29 @@ client.upsert("{collection_name}", { }); ``` +```rust +use qdrant_client::{client::QdrantClient, qdrant::PointStruct}; +use serde_json::json; + +let client = QdrantClient::from_url("http://localhost:6334").build()?; + +client + .upsert_points_blocking( + "{collection_name}".to_string(), + vec![PointStruct::new( + "5c56c793-69f3-4fbf-87e6-c4bf54c28c26".to_string(), + vec![0.05, 0.61, 0.76, 0.74], + json!( + {"color": "Red"} + ) + .try_into() + .unwrap(), + )], + None, + ) + .await?; +``` + and ```http @@ -165,6 +188,27 @@ client.upsert("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::PointStruct; +use serde_json::json; + +client + .upsert_points_blocking( + 1, + vec![PointStruct::new( + "5c56c793-69f3-4fbf-87e6-c4bf54c28c26".to_string(), + vec![0.05, 0.61, 0.76, 0.74], + json!( + {"color": "Red"} + ) + .try_into() + .unwrap(), + )], + None, + ) + .await?; +``` + are both possible. ## Upload points @@ -230,6 +274,7 @@ client.upsert("{collection_name}", { }); ``` + or record-oriented equivalent: ```http @@ -307,6 +352,48 @@ client.upsert("{collection_name}", { }); ``` +```rust +use qdrant_client::qdrant::PointStruct; +use serde_json::json; + +client + .upsert_points_batch_blocking( + "{collection_name}".to_string(), + vec![ + PointStruct::new( + 1, + vec![0.9, 0.1, 0.1], + json!( + {"color": "red"} + ) + .try_into() + .unwrap(), + ), + PointStruct::new( + 2, + vec![0.1, 0.9, 0.1], + json!( + {"color": "green"} + ) + .try_into() + .unwrap(), + ), + PointStruct::new( + 3, + vec![0.1, 0.1, 0.9], + json!( + {"color": "blue"} + ) + .try_into() + .unwrap(), + ), + ], + None, + 100, + ) + .await?; +``` +