#![doc(html_logo_url = "https://qdrant.tech/favicon/android-chrome-192x192.png")]
#![doc(issue_tracker_base_url = "https://github.com/qdrant/rust-client/issues/")]
#[allow(deprecated, clippy::all)]
#[rustfmt::skip]
pub mod qdrant;
mod auth;
mod builder_ext;
mod builder_types;
mod builders;
mod channel_pool;
mod expressions;
mod filters;
mod grpc_conversions;
mod grpc_macros;
mod manual_builder;
mod payload;
mod qdrant_client;
#[cfg(feature = "serde")]
mod serde_impl;
#[cfg(feature = "serde")]
pub mod serde_deser;
pub use crate::payload::Payload;
pub use crate::qdrant_client::error::QdrantError;
pub use crate::qdrant_client::{Qdrant, QdrantBuilder};
pub mod config {
pub use crate::qdrant_client::config::{
AsOptionApiKey, AsTimeout, CompressionEncoding, QdrantConfig,
};
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use crate::builders::CreateCollectionBuilder;
use crate::payload::Payload;
use crate::qdrant::value::Kind::*;
use crate::qdrant::{
Condition, CreateFieldIndexCollection, DeletePayloadPointsBuilder, DeletePointsBuilder,
Distance, FieldType, Filter, GetPointsBuilder, ListValue, PointStruct, SearchPointsBuilder,
SetPayloadPointsBuilder, SnapshotDownloadBuilder, Struct, UpsertPointsBuilder, Value,
VectorParamsBuilder,
};
use crate::Qdrant;
#[test]
fn display() {
let value = Value {
kind: Some(StructValue(Struct {
fields: [
("text", StringValue("Hi Qdrant!".into())),
("int", IntegerValue(42)),
("float", DoubleValue(1.23)),
(
"list",
ListValue(ListValue {
values: vec![Value {
kind: Some(NullValue(0)),
}],
}),
),
(
"struct",
StructValue(Struct {
fields: [(
"bool".into(),
Value {
kind: Some(BoolValue(true)),
},
)]
.into(),
}),
),
]
.into_iter()
.map(|(k, v)| (k.into(), Value { kind: Some(v) }))
.collect(),
})),
};
let text = format!("{value}");
assert!([
"\"float\":1.23",
"\"list\":[null]",
"\"struct\":{\"bool\":true}",
"\"int\":42",
"\"text\":\"Hi Qdrant!\""
]
.into_iter()
.all(|item| text.contains(item)));
}
#[tokio::test]
async fn test_qdrant_queries() -> anyhow::Result<()> {
let client = Qdrant::from_url("http://localhost:6334")
.timeout(10u64) .build()?;
let health = client.health_check().await?;
println!("{health:?}");
let collections_list = client.list_collections().await?;
println!("{collections_list:?}");
let collection_name = "test_qdrant_queries";
client.delete_collection(collection_name).await?;
client
.create_collection(
CreateCollectionBuilder::new(collection_name)
.vectors_config(VectorParamsBuilder::new(10, Distance::Cosine)),
)
.await?;
let exists = client.collection_exists(collection_name).await?;
assert!(exists);
let collection_info = client.collection_info(collection_name).await?;
println!("{collection_info:#?}");
let mut sub_payload = Payload::new();
sub_payload.insert("foo", "Not bar");
let payload: Payload = vec![
("foo", "Bar".into()),
("bar", 12.into()),
("sub_payload", sub_payload.into()),
]
.into_iter()
.collect::<HashMap<_, Value>>()
.into();
let points = vec![PointStruct::new(0, vec![12.; 10], payload)];
client
.upsert_points(UpsertPointsBuilder::new(collection_name, points).wait(true))
.await?;
let mut search_points =
SearchPointsBuilder::new(collection_name, vec![11.; 10], 10).build();
search_points.filter = Some(Filter::all([Condition::matches("foo", "Bar".to_string())]));
let search_result = client.search_points(search_points.clone()).await?;
eprintln!("search_result = {search_result:#?}");
assert!(!search_result.result.is_empty());
search_points.filter = Some(Filter::all([Condition::matches(
"sub_payload.foo",
"Not ".to_string(),
)]));
let search_result = client.search_points(search_points.clone()).await?;
eprintln!("search_result = {search_result:#?}");
assert!(!search_result.result.is_empty());
search_points.filter = Some(Filter::all([Condition::matches_text(
"sub_payload.foo",
"Not",
)]));
let search_result = client.search_points(search_points).await?;
eprintln!("search_result = {search_result:#?}");
assert!(!search_result.result.is_empty());
let new_payload: Payload = vec![("foo", "BAZ".into())]
.into_iter()
.collect::<HashMap<_, Value>>()
.into();
let payload_result = client
.set_payload(
SetPayloadPointsBuilder::new(collection_name, new_payload).points_selector([0]),
)
.await?;
eprintln!("payload_result = {payload_result:#?}");
client
.delete_payload(
DeletePayloadPointsBuilder::new(collection_name, ["sub_payload".into()])
.points_selector([0]),
)
.await?;
let get_points_result = client
.get_points(
GetPointsBuilder::new(collection_name, [0.into()])
.with_vectors(true)
.with_payload(true),
)
.await?;
eprintln!("get_points_result = {get_points_result:#?}");
assert_eq!(get_points_result.result.len(), 1);
let point = get_points_result.result[0].clone();
assert!(point.payload.contains_key("foo"));
assert!(!point.payload.contains_key("sub_payload"));
let delete_points_result = client
.delete_points(
DeletePointsBuilder::new(collection_name)
.points([0])
.wait(true),
)
.await?;
eprintln!("delete_points_result = {delete_points_result:#?}");
client
.with_points_client(|mut client| async move {
client
.create_field_index(CreateFieldIndexCollection {
collection_name: collection_name.to_string(),
wait: None,
field_name: "foo".to_string(),
field_type: Some(FieldType::Keyword as i32),
field_index_params: None,
ordering: None,
timeout: None,
})
.await
})
.await?;
let snapshot_result = client.create_snapshot(collection_name).await?;
eprintln!("snapshot_result = {snapshot_result:#?}");
#[cfg(feature = "download_snapshots")]
client
.download_snapshot(SnapshotDownloadBuilder::new("test.tar", collection_name))
.await?;
Ok(())
}
}