pub struct QdrantOps { /* private fields */ }Expand description
Thin wrapper over Qdrant client encapsulating common collection operations.
Implementations§
Source§impl QdrantOps
impl QdrantOps
Sourcepub fn new(url: &str, api_key: Option<&str>) -> Result<Self, Box<QdrantError>>
pub fn new(url: &str, api_key: Option<&str>) -> Result<Self, Box<QdrantError>>
Create a new QdrantOps connected to the given URL with optional API key.
When api_key is Some(k) and k is non-empty, the key is attached to the gRPC
client builder. Empty strings are treated as None so callers can pass empty config
values without accidentally disabling auth.
The key is consumed by qdrant-client during .build() and is never stored on
QdrantOps itself.
§Errors
Returns an error if the Qdrant client cannot be created (e.g. malformed URL).
Sourcepub fn with_timeout(self, timeout: Duration) -> Self
pub fn with_timeout(self, timeout: Duration) -> Self
Override the per-call timeout applied to every Qdrant gRPC operation.
Defaults to 10 seconds. A slow or hung Qdrant server would otherwise block the
calling async task indefinitely (#5484). The production bootstrap path drives this
from MemoryConfig::qdrant_timeout_secs.
§Examples
use std::time::Duration;
use zeph_memory::QdrantOps;
let ops = QdrantOps::new("http://localhost:6334", None)
.unwrap()
.with_timeout(Duration::from_secs(3));Sourcepub fn client(&self) -> &Qdrant
pub fn client(&self) -> &Qdrant
Access the underlying Qdrant client for advanced operations.
§Warning
Calls made directly through the returned client bypass the Self::with_timeout
guard (#5484) — they are not wrapped by Self::timed. Prefer the inherent
QdrantOps methods, which are all timeout-guarded, unless the client exposes an
operation this type does not wrap.
Sourcepub async fn ensure_collection(
&self,
collection: &str,
vector_size: u64,
) -> Result<(), Box<QdrantError>>
pub async fn ensure_collection( &self, collection: &str, vector_size: u64, ) -> Result<(), Box<QdrantError>>
Ensure a collection exists with cosine distance vectors.
If the collection already exists but has a different vector dimension than vector_size,
the collection is deleted and recreated. All existing data in the collection is lost.
Callers on interactive/destructive-sensitive paths should pre-check via
Self::collection_exists + Self::get_collection_vector_size and gate the call
behind explicit confirmation instead of relying on this method’s silent recreate (see
zeph knowledge ingest’s notes-sink resource setup for the reference pattern, #5444).
§Errors
Returns an error if Qdrant cannot be reached or collection creation fails.
Sourcepub async fn get_collection_vector_size(
&self,
collection: &str,
) -> Result<Option<u64>, Box<QdrantError>>
pub async fn get_collection_vector_size( &self, collection: &str, ) -> Result<Option<u64>, Box<QdrantError>>
Returns the configured vector size of an existing collection, or None if it cannot be
determined (e.g. named-vector collections).
§Precondition
The caller must already know the collection exists (e.g. via a prior
Self::collection_exists check that returned true). This method does not treat
“collection missing” and “dimension unreadable” as the same case: calling it on a
non-existent collection surfaces the underlying collection_info gRPC error (Err), it
does not return Ok(None). Every existing call site (this type’s own
Self::ensure_collection, crate::EmbeddingRegistry) checks collection_exists
first for this reason.
Used by crate::EmbeddingRegistry to validate query vector dimensions before issuing
gRPC searches. Qdrant gRPC silently returns near-zero cosine scores when the query vector
dimension does not match the stored collection dimension (unlike REST which returns 400).
Also used by callers that need to detect an Self::ensure_collection dimension mismatch
before invoking it, so a destructive recreate can be gated behind confirmation.
§Errors
Returns an error on hard Qdrant communication failures, including calling this on a collection that does not exist (see Precondition above).
Sourcepub async fn collection_exists(
&self,
collection: &str,
) -> Result<bool, Box<QdrantError>>
pub async fn collection_exists( &self, collection: &str, ) -> Result<bool, Box<QdrantError>>
Sourcepub async fn delete_collection(
&self,
collection: &str,
) -> Result<(), Box<QdrantError>>
pub async fn delete_collection( &self, collection: &str, ) -> Result<(), Box<QdrantError>>
Sourcepub async fn upsert(
&self,
collection: &str,
points: Vec<PointStruct>,
) -> Result<(), Box<QdrantError>>
pub async fn upsert( &self, collection: &str, points: Vec<PointStruct>, ) -> Result<(), Box<QdrantError>>
Sourcepub async fn search(
&self,
collection: &str,
vector: Vec<f32>,
limit: u64,
filter: Option<Filter>,
) -> Result<Vec<ScoredPoint>, Box<QdrantError>>
pub async fn search( &self, collection: &str, vector: Vec<f32>, limit: u64, filter: Option<Filter>, ) -> Result<Vec<ScoredPoint>, Box<QdrantError>>
Search for similar vectors, returning scored points with payloads.
Uses the Qdrant Query API (client.query) which handles query vector normalization
server-side for Cosine collections, producing correct similarity scores.
§Errors
Returns an error if the search fails.
Sourcepub async fn delete_by_ids(
&self,
collection: &str,
ids: Vec<PointId>,
) -> Result<(), Box<QdrantError>>
pub async fn delete_by_ids( &self, collection: &str, ids: Vec<PointId>, ) -> Result<(), Box<QdrantError>>
Sourcepub async fn scroll_all(
&self,
collection: &str,
key_field: &str,
) -> Result<HashMap<String, HashMap<String, String>>, Box<QdrantError>>
pub async fn scroll_all( &self, collection: &str, key_field: &str, ) -> Result<HashMap<String, HashMap<String, String>>, Box<QdrantError>>
Scroll all points in a collection, extracting string payload fields.
Returns a map of key_field value -> { field_name -> field_value }.
§Errors
Returns an error if the scroll operation fails.
Sourcepub async fn scroll_all_with_point_ids(
&self,
collection: &str,
key_field: &str,
) -> Result<Vec<(String, HashMap<String, String>)>, Box<QdrantError>>
pub async fn scroll_all_with_point_ids( &self, collection: &str, key_field: &str, ) -> Result<Vec<(String, HashMap<String, String>)>, Box<QdrantError>>
Scroll all points in a collection, returning (point_id, string_payload_fields) pairs.
Only points whose payload contains key_field as a StringValue are included.
The Qdrant point ID is preserved as the first tuple element.
§Errors
Returns an error if the scroll operation fails.
Sourcepub async fn ensure_collection_with_quantization(
&self,
collection: &str,
vector_size: u64,
keyword_fields: &[&str],
) -> Result<(), VectorStoreError>
pub async fn ensure_collection_with_quantization( &self, collection: &str, vector_size: u64, keyword_fields: &[&str], ) -> Result<(), VectorStoreError>
Create a collection with scalar INT8 quantization if it does not exist, then create keyword indexes for the given fields.
If the collection already exists but has a different vector dimension than vector_size,
the collection is deleted and recreated. All existing data in the collection is lost.
§Errors
Returns an error if any Qdrant operation fails.
Trait Implementations§
Source§impl VectorStore for QdrantOps
impl VectorStore for QdrantOps
Source§fn ensure_collection(
&self,
collection: &str,
vector_size: u64,
) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
fn ensure_collection( &self, collection: &str, vector_size: u64, ) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
vector_size dimensions. Read moreSource§fn collection_exists(
&self,
collection: &str,
) -> Pin<Box<dyn Future<Output = Result<bool, VectorStoreError>> + Send + '_>>
fn collection_exists( &self, collection: &str, ) -> Pin<Box<dyn Future<Output = Result<bool, VectorStoreError>> + Send + '_>>
true if collection exists in the backend.Source§fn delete_collection(
&self,
collection: &str,
) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
fn delete_collection( &self, collection: &str, ) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
Source§fn upsert(
&self,
collection: &str,
points: Vec<VectorPoint>,
) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
fn upsert( &self, collection: &str, points: Vec<VectorPoint>, ) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
Source§fn search(
&self,
collection: &str,
vector: Vec<f32>,
limit: u64,
filter: Option<VectorFilter>,
) -> Pin<Box<dyn Future<Output = Result<Vec<ScoredVectorPoint>, VectorStoreError>> + Send + '_>>
fn search( &self, collection: &str, vector: Vec<f32>, limit: u64, filter: Option<VectorFilter>, ) -> Pin<Box<dyn Future<Output = Result<Vec<ScoredVectorPoint>, VectorStoreError>> + Send + '_>>
Source§fn delete_by_ids(
&self,
collection: &str,
ids: Vec<String>,
) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
fn delete_by_ids( &self, collection: &str, ids: Vec<String>, ) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
collection by their string IDs.Source§fn scroll_all(
&self,
collection: &str,
key_field: &str,
) -> Pin<Box<dyn Future<Output = Result<HashMap<String, HashMap<String, String>>, VectorStoreError>> + Send + '_>>
fn scroll_all( &self, collection: &str, key_field: &str, ) -> Pin<Box<dyn Future<Output = Result<HashMap<String, HashMap<String, String>>, VectorStoreError>> + Send + '_>>
collection and return a map of
point_id → { key_field → value } payload entries.Source§fn scroll_all_with_point_ids(
&self,
collection: &str,
key_field: &str,
) -> Pin<Box<dyn Future<Output = Result<ScrollWithIdsResult, VectorStoreError>> + Send + '_>>
fn scroll_all_with_point_ids( &self, collection: &str, key_field: &str, ) -> Pin<Box<dyn Future<Output = Result<ScrollWithIdsResult, VectorStoreError>> + Send + '_>>
Source§fn health_check(
&self,
) -> Pin<Box<dyn Future<Output = Result<bool, VectorStoreError>> + Send + '_>>
fn health_check( &self, ) -> Pin<Box<dyn Future<Output = Result<bool, VectorStoreError>> + Send + '_>>
true if the backend is reachable and operational.Source§fn create_keyword_indexes(
&self,
collection: &str,
fields: &[&str],
) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
fn create_keyword_indexes( &self, collection: &str, fields: &[&str], ) -> Pin<Box<dyn Future<Output = Result<(), VectorStoreError>> + Send + '_>>
Source§fn get_points(
&self,
collection: &str,
ids: Vec<String>,
) -> Pin<Box<dyn Future<Output = Result<Vec<VectorPoint>, VectorStoreError>> + Send + '_>>
fn get_points( &self, collection: &str, ids: Vec<String>, ) -> Pin<Box<dyn Future<Output = Result<Vec<VectorPoint>, VectorStoreError>> + Send + '_>>
Auto Trait Implementations§
impl !RefUnwindSafe for QdrantOps
impl !UnwindSafe for QdrantOps
impl Freeze for QdrantOps
impl Send for QdrantOps
impl Sync for QdrantOps
impl Unpin for QdrantOps
impl UnsafeUnpin for QdrantOps
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request