Skip to main content

VecDex

Struct VecDex 

Source
pub struct VecDex<K, D, S: Scalar = f32>
where K: KeyEnDe + ValueEnDe + Clone + Eq, D: DistanceMetric<S>,
{ /* private fields */ }
Expand description

A persistent, disk-backed approximate nearest-neighbor index using the HNSW (Hierarchical Navigable Small World) algorithm.

Type parameters:

  • K: user-facing key type.
  • D: distance metric (L2, Cosine, InnerProduct).
  • S: scalar type for vector components (f32 or f64, default f32).

Each mutation or bulk-insert chunk uses one atomic engine batch for rows and graph state. This preserves their consistency across recovery under the ownership contract below; it does not imply power-loss durability for every successful call.

§Handle ownership

Serde deserialization and from_meta restore a handle to the same storage, with independent in-memory caches. Recovery replaces the active handle: retire the previous handle before using the restored one for mutations. Alternating writes through restored aliases can corrupt counters or index state, even when those writes are serialized.

While mutations occur, route every read and write through one live instance (for example, share it behind a Mutex or RwLock). Multiple independent handles may read the same index only while no handle mutates it.

Implementations§

Source§

impl<K, D, S> VecDex<K, D, S>
where K: KeyEnDe + ValueEnDe + Clone + Eq, D: DistanceMetric<S>, S: Scalar,

Source

pub fn new_in(ns: &Namespace, config: HnswConfig) -> Result<Self>

new placed in ns — every internal component lands in the same namespace (a composite never spans namespaces).

Source

pub fn namespace(&self) -> Namespace

The namespace this structure lives in.

Source

pub fn new(config: HnswConfig) -> Result<Self>

Creates a new, empty VecDex with the given configuration.

§Errors

VsdbError::InvalidConfig unless dim > 0, m >= 2, m_max0 >= m (else base-layer nodes have no edges and become unreachable) and ef_construction > 0 (else a layer search returns no candidates). VsdbError::ReadOnly in read-only mode.

Source

pub fn instance_id(&self) -> InstanceId

Returns the unique instance ID.

Source

pub fn save_meta(&self) -> Result<InstanceId>

Persists this instance’s metadata to disk so that it can be recovered later via from_meta.

The metadata is create-time constant (single handle + creation config), so calling this once after creation is sufficient for the lifetime of the instance.

Source

pub fn from_meta(instance_id: impl Into<InstanceId>) -> Result<Self>

Recovers a VecDex from previously saved metadata.

Hydrates runtime caches from persisted rows and graph state. Each mutation or bulk-insert chunk commits those rows together; recovery does not rebuild the graph.

This replaces the active handle; it does not share caches with existing aliases. The handle ownership contract also applies to direct serde deserialization.

Source

pub fn len(&self) -> u64

Returns the number of indexed vectors.

Source

pub fn is_empty(&self) -> bool

Returns true if the index contains no vectors.

Updates the default search beam width (persisted).

§Errors

VsdbError::ReadOnly in read-only mode, or the commit error; nothing changes in either case.

Source

pub fn get(&self, key: &K) -> Option<Vec<S>>

Returns the vector associated with the given key, if it exists.

Source

pub fn contains_key(&self, key: &K) -> bool

Returns true if the index contains the given key.

Source

pub fn keys(&self) -> impl Iterator<Item = K> + '_

Returns an iterator over all indexed keys.

Source

pub fn iter(&self) -> impl Iterator<Item = (K, Vec<S>)> + '_

Returns an iterator over all (key, vector) pairs.

Source

pub fn clear(&mut self) -> Result<()>

Clears all indexed data.

The wipe (one engine-level range tombstone) and the reset graph state row — which preserves the live ef_search, also across a later restore — commit in one atomic engine write batch: a crash can never expose a partially-cleared index.

§Errors

VsdbError::ReadOnly in read-only mode, or the commit error; nothing changes in either case.

Source

pub fn insert(&mut self, key: &K, vector: &[S]) -> Result<()>

Inserts a vector associated with a user key.

If the key already exists, removal of the old node and insertion of the replacement are staged in the same atomic batch.

All rows of the insert proper — the vector, both key mappings, the node info, every adjacency update, and the graph state — are committed through one atomic engine batch.

§Errors

If the vector dimension mismatches the index configuration, or if the batch commit fails (in which case neither the on-disk state nor the in-memory state is modified).

Source

pub fn insert_batch(&mut self, items: &[(K, Vec<S>)]) -> Result<()>

Inserts a batch of (key, vector) pairs.

Semantically equivalent to calling insert in a loop, but the inserts are staged in chunks that share one transaction (and thus one atomic engine write batch) each — amortizing the per-commit cost, which dominates bulk loads.

Pre-existing keys are removed and reinserted inside their chunk’s atomic transaction, and duplicate keys inside items collapse to the last occurrence.

Source

pub fn search(&self, query: &[S], k: usize) -> Result<Vec<(K, S)>>

Searches for the k nearest neighbors of the query vector.

Source

pub fn search_ef(&self, query: &[S], k: usize, ef: usize) -> Result<Vec<(K, S)>>

Searches with a custom ef (beam width) for recall/speed tradeoff.

Source

pub fn search_with_filter( &self, query: &[S], k: usize, predicate: impl Fn(&K) -> bool, ) -> Result<Vec<(K, S)>>

Searches with a key predicate evaluated during beam search.

Non-matching nodes still participate in graph traversal to maintain connectivity, but are excluded from the result set. The search keeps expanding until it holds max(ef, k) matching candidates and the frontier is farther than the worst of them, so a selective predicate costs more visited nodes (roughly ∝ 1 / selectivity) rather than fewer results; a predicate that almost nothing satisfies stops at a visit cap of max(64 × max(ef, k), 4096) evaluated nodes.

Use search_ef_with_filter to trade recall against work explicitly.

Source

pub fn search_ef_with_filter( &self, query: &[S], k: usize, ef: usize, predicate: impl Fn(&K) -> bool, ) -> Result<Vec<(K, S)>>

Filtered search with a custom ef (beam width).

Source

pub fn remove(&mut self, key: &K) -> Result<bool>

Removes a vector by user key. Returns true if the key existed.

Former neighbors of the removed node are reconnected to each other (best-effort) to preserve graph connectivity. Every row update — edge rewires, row removals, and the graph state — is committed through one atomic engine batch.

§Errors

If the batch commit fails, neither the on-disk state nor the in-memory state is modified.

Source

pub fn compact(&mut self) -> Result<()>

Rebuilds the HNSW graph from the existing vectors.

Useful after many deletions to restore graph quality and recall. Vectors are re-inserted in random order for better graph quality.

The whole rebuild is staged through one wiped transaction: the range tombstone and every row of the new graph commit in a single atomic engine write batch, so a crash (or an error return) leaves either the old graph or the new one — never anything in between. This is a cold maintenance API: the new graph is staged in memory before the commit, so expect transient memory proportional to the index size.

Trait Implementations§

Source§

impl<K, D, S> Debug for VecDex<K, D, S>
where K: KeyEnDe + ValueEnDe + Clone + Eq, D: DistanceMetric<S>, S: Scalar,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de, K, D, S> Deserialize<'de> for VecDex<K, D, S>
where K: KeyEnDe + ValueEnDe + Clone + Eq, D: DistanceMetric<S>, S: Scalar,

Source§

fn deserialize<De>(deserializer: De) -> Result<Self, De::Error>
where De: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<K, D, S> Serialize for VecDex<K, D, S>
where K: KeyEnDe + ValueEnDe + Clone + Eq, D: DistanceMetric<S>, S: Scalar,

Source§

fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
where Ser: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<K, D, S = f32> !Freeze for VecDex<K, D, S>

§

impl<K, D, S = f32> !RefUnwindSafe for VecDex<K, D, S>

§

impl<K, D, S = f32> !UnwindSafe for VecDex<K, D, S>

§

impl<K, D, S> Send for VecDex<K, D, S>

§

impl<K, D, S> Sync for VecDex<K, D, S>

§

impl<K, D, S> Unpin for VecDex<K, D, S>

§

impl<K, D, S> UnsafeUnpin for VecDex<K, D, S>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> KeyDe for T

Source§

fn decode_key(bytes: &[u8]) -> Result<T, VsdbError>

Decodes a key from a byte slice. Read more
Source§

impl<T> KeyEn for T
where T: Serialize,

Source§

fn try_encode_key(&self) -> Result<Vec<u8>, VsdbError>

Attempts to encode the key. Returns Err only if the Serialize implementation is broken — see module-level trust model for details.
Source§

fn encode_key(&self) -> RawBytes

Encodes the key, panicking on failure. Read more
Source§

impl<T> KeyEnDe for T
where T: KeyEn + KeyDe,

Source§

fn try_encode(&self) -> Result<Vec<u8>, VsdbError>

Attempts to encode the key. Prefer encode for internal VSDB paths; use this at trust boundaries where a Result is needed.
Source§

fn encode(&self) -> Vec<u8> ⓘ

Encodes the key, panicking on failure. Read more
Source§

fn decode(bytes: &[u8]) -> Result<T, VsdbError>

Decodes a key from a byte slice. Read more
Source§

impl<T> KeyRef for T
where T: KeyEnDe,

Source§

fn key_bytes(&self) -> Vec<u8> ⓘ

The stored-key bytes this value addresses.
Source§

fn as_byte_slice(&self) -> Option<&[u8]>

Byte-slice contents, when this is a borrowed byte-slice query. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> ValueDe for T

Source§

fn decode_value(bytes: &[u8]) -> Result<T, VsdbError>

Decodes a value from a byte slice. Read more
Source§

impl<T> ValueEn for T
where T: Serialize,

Source§

fn try_encode_value(&self) -> Result<Vec<u8>, VsdbError>

Attempts to encode the value. Returns Err only if the Serialize implementation is broken.
Source§

fn encode_value(&self) -> RawBytes

Encodes the value, panicking on failure. Read more
Source§

impl<T> ValueEnDe for T
where T: ValueEn + ValueDe,

Source§

fn try_encode(&self) -> Result<Vec<u8>, VsdbError>

Attempts to encode the value. Prefer encode for internal VSDB paths; use this at trust boundaries where a Result is needed.
Source§

fn encode(&self) -> Vec<u8> ⓘ

Encodes the value, panicking on failure. Read more
Source§

fn decode(bytes: &[u8]) -> Result<T, VsdbError>

Decodes a value from a byte slice. Read more
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more