pub struct VectorStore {
pub vectors: Vec<Vector>,
pub hnsw_index: Option<HNSWIndex>,
pub id_to_index: FxHashMap<String, usize>,
/* private fields */
}Expand description
Vector store with HNSW indexing
Fields§
§vectors: Vec<Vector>All vectors stored in memory (used for rescore when quantization enabled)
hnsw_index: Option<HNSWIndex>HNSW index for approximate nearest neighbor search
id_to_index: FxHashMap<String, usize>Map from string IDs to internal indices (public for Python bindings)
Implementations§
Source§impl VectorStore
impl VectorStore
Sourcepub fn new_with_quantization(dimensions: usize, mode: QuantizationMode) -> Self
pub fn new_with_quantization(dimensions: usize, mode: QuantizationMode) -> Self
Create new vector store with quantization
Quantization is trained on the first batch of vectors inserted.
Sourcepub fn new_with_params(
dimensions: usize,
m: usize,
ef_construction: usize,
ef_search: usize,
distance_metric: Metric,
) -> Result<Self>
pub fn new_with_params( dimensions: usize, m: usize, ef_construction: usize, ef_search: usize, distance_metric: Metric, ) -> Result<Self>
Create new vector store with custom HNSW parameters
Sourcepub fn open(path: impl AsRef<Path>) -> Result<Self>
pub fn open(path: impl AsRef<Path>) -> Result<Self>
Open a persistent vector store at the given path
Creates a new database if it doesn’t exist, or loads existing data. All operations (insert, set, delete) are automatically persisted.
§Arguments
path- Directory path for the database (e.g., “mydb.oadb”)
§Example
let mut store = VectorStore::open("mydb.oadb")?;
store.set("doc1".to_string(), vector, metadata)?;
// Data is automatically persistedSourcepub fn open_with_dimensions(
path: impl AsRef<Path>,
dimensions: usize,
) -> Result<Self>
pub fn open_with_dimensions( path: impl AsRef<Path>, dimensions: usize, ) -> Result<Self>
Open a persistent vector store with specified dimensions
Like open() but ensures dimensions are set for new databases.
Sourcepub fn open_with_options(
path: impl AsRef<Path>,
options: &VectorStoreOptions,
) -> Result<Self>
pub fn open_with_options( path: impl AsRef<Path>, options: &VectorStoreOptions, ) -> Result<Self>
Open a persistent vector store with custom options.
This is the internal implementation used by VectorStoreOptions::open().
Sourcepub fn build_with_options(options: &VectorStoreOptions) -> Result<Self>
pub fn build_with_options(options: &VectorStoreOptions) -> Result<Self>
Build an in-memory vector store with custom options.
Sourcepub fn insert_with_metadata(
&mut self,
id: String,
vector: Vector,
metadata: JsonValue,
) -> Result<usize>
pub fn insert_with_metadata( &mut self, id: String, vector: Vector, metadata: JsonValue, ) -> Result<usize>
Insert vector with string ID and metadata
This is the primary method for inserting vectors with metadata support. Returns error if ID already exists (use set for insert-or-update semantics).
Sourcepub fn set(
&mut self,
id: String,
vector: Vector,
metadata: JsonValue,
) -> Result<usize>
pub fn set( &mut self, id: String, vector: Vector, metadata: JsonValue, ) -> Result<usize>
Upsert vector (insert or update) with string ID and metadata
This is the recommended method for most use cases.
Sourcepub fn set_batch(
&mut self,
batch: Vec<(String, Vector, JsonValue)>,
) -> Result<Vec<usize>>
pub fn set_batch( &mut self, batch: Vec<(String, Vector, JsonValue)>, ) -> Result<Vec<usize>>
Batch set vectors (insert or update multiple vectors at once)
This is the recommended method for bulk operations.
Sourcepub fn enable_text_search(&mut self) -> Result<()>
pub fn enable_text_search(&mut self) -> Result<()>
Enable text search on this store
Sourcepub fn enable_text_search_with_config(
&mut self,
config: Option<TextSearchConfig>,
) -> Result<()>
pub fn enable_text_search_with_config( &mut self, config: Option<TextSearchConfig>, ) -> Result<()>
Enable text search with custom configuration
Sourcepub fn has_text_search(&self) -> bool
pub fn has_text_search(&self) -> bool
Check if text search is enabled
Sourcepub fn set_with_text(
&mut self,
id: String,
vector: Vector,
text: &str,
metadata: JsonValue,
) -> Result<usize>
pub fn set_with_text( &mut self, id: String, vector: Vector, text: &str, metadata: JsonValue, ) -> Result<usize>
Upsert vector with text content for hybrid search
Sourcepub fn set_batch_with_text(
&mut self,
batch: Vec<(String, Vector, String, JsonValue)>,
) -> Result<Vec<usize>>
pub fn set_batch_with_text( &mut self, batch: Vec<(String, Vector, String, JsonValue)>, ) -> Result<Vec<usize>>
Batch upsert vectors with text content for hybrid search
Sourcepub fn text_search(&self, query: &str, k: usize) -> Result<Vec<(String, f32)>>
pub fn text_search(&self, query: &str, k: usize) -> Result<Vec<(String, f32)>>
Search text index only (BM25 scoring)
Sourcepub fn hybrid_search(
&mut self,
query_vector: &Vector,
query_text: &str,
k: usize,
alpha: Option<f32>,
) -> Result<Vec<(String, f32, JsonValue)>>
pub fn hybrid_search( &mut self, query_vector: &Vector, query_text: &str, k: usize, alpha: Option<f32>, ) -> Result<Vec<(String, f32, JsonValue)>>
Hybrid search combining vector similarity and BM25 text relevance
Sourcepub fn hybrid_search_with_rrf_k(
&mut self,
query_vector: &Vector,
query_text: &str,
k: usize,
alpha: Option<f32>,
rrf_k: Option<usize>,
) -> Result<Vec<(String, f32, JsonValue)>>
pub fn hybrid_search_with_rrf_k( &mut self, query_vector: &Vector, query_text: &str, k: usize, alpha: Option<f32>, rrf_k: Option<usize>, ) -> Result<Vec<(String, f32, JsonValue)>>
Hybrid search with configurable RRF k constant
Sourcepub fn hybrid_search_with_filter(
&mut self,
query_vector: &Vector,
query_text: &str,
k: usize,
filter: &MetadataFilter,
alpha: Option<f32>,
) -> Result<Vec<(String, f32, JsonValue)>>
pub fn hybrid_search_with_filter( &mut self, query_vector: &Vector, query_text: &str, k: usize, filter: &MetadataFilter, alpha: Option<f32>, ) -> Result<Vec<(String, f32, JsonValue)>>
Hybrid search with filter
Sourcepub fn hybrid_search_with_filter_rrf_k(
&mut self,
query_vector: &Vector,
query_text: &str,
k: usize,
filter: &MetadataFilter,
alpha: Option<f32>,
rrf_k: Option<usize>,
) -> Result<Vec<(String, f32, JsonValue)>>
pub fn hybrid_search_with_filter_rrf_k( &mut self, query_vector: &Vector, query_text: &str, k: usize, filter: &MetadataFilter, alpha: Option<f32>, rrf_k: Option<usize>, ) -> Result<Vec<(String, f32, JsonValue)>>
Hybrid search with filter and configurable RRF k constant
Sourcepub fn hybrid_search_with_subscores(
&mut self,
query_vector: &Vector,
query_text: &str,
k: usize,
alpha: Option<f32>,
rrf_k: Option<usize>,
) -> Result<Vec<(HybridResult, JsonValue)>>
pub fn hybrid_search_with_subscores( &mut self, query_vector: &Vector, query_text: &str, k: usize, alpha: Option<f32>, rrf_k: Option<usize>, ) -> Result<Vec<(HybridResult, JsonValue)>>
Hybrid search returning separate keyword and semantic scores.
Returns HybridResult with keyword_score (BM25) and semantic_score (vector distance)
for each result, enabling custom post-processing or debugging.
Sourcepub fn hybrid_search_with_filter_subscores(
&mut self,
query_vector: &Vector,
query_text: &str,
k: usize,
filter: &MetadataFilter,
alpha: Option<f32>,
rrf_k: Option<usize>,
) -> Result<Vec<(HybridResult, JsonValue)>>
pub fn hybrid_search_with_filter_subscores( &mut self, query_vector: &Vector, query_text: &str, k: usize, filter: &MetadataFilter, alpha: Option<f32>, rrf_k: Option<usize>, ) -> Result<Vec<(HybridResult, JsonValue)>>
Hybrid search with filter returning separate keyword and semantic scores.
Sourcepub fn update(
&mut self,
id: &str,
vector: Option<Vector>,
metadata: Option<JsonValue>,
) -> Result<()>
pub fn update( &mut self, id: &str, vector: Option<Vector>, metadata: Option<JsonValue>, ) -> Result<()>
Update existing vector by string ID
Sourcepub fn delete(&mut self, id: &str) -> Result<()>
pub fn delete(&mut self, id: &str) -> Result<()>
Delete vector by string ID
This method:
- Marks the vector as deleted (soft delete)
- Repairs the HNSW graph using MN-RU algorithm to maintain recall quality
- Removes from text index if present
- Persists to WAL
Sourcepub fn delete_batch(&mut self, ids: &[String]) -> Result<usize>
pub fn delete_batch(&mut self, ids: &[String]) -> Result<usize>
Delete multiple vectors by string IDs
Uses batch MN-RU graph repair for better efficiency than individual deletes.
Sourcepub fn delete_by_filter(&mut self, filter: &MetadataFilter) -> Result<usize>
pub fn delete_by_filter(&mut self, filter: &MetadataFilter) -> Result<usize>
Sourcepub fn count_by_filter(&self, filter: &MetadataFilter) -> usize
pub fn count_by_filter(&self, filter: &MetadataFilter) -> usize
Sourcepub fn get(&self, id: &str) -> Option<(Vector, JsonValue)>
pub fn get(&self, id: &str) -> Option<(Vector, JsonValue)>
Get vector by string ID
Returns owned data since vectors may be loaded from disk for quantized stores.
Sourcepub fn get_batch(
&self,
ids: &[impl AsRef<str>],
) -> Vec<Option<(Vector, JsonValue)>>
pub fn get_batch( &self, ids: &[impl AsRef<str>], ) -> Vec<Option<(Vector, JsonValue)>>
Get multiple vectors by string IDs
Returns a vector of results in the same order as input IDs. Missing/deleted IDs return None in their position.
Sourcepub fn get_metadata_by_id(&self, id: &str) -> Option<&JsonValue>
pub fn get_metadata_by_id(&self, id: &str) -> Option<&JsonValue>
Get metadata by string ID (without loading vector data)
Sourcepub fn batch_insert(&mut self, vectors: Vec<Vector>) -> Result<Vec<usize>>
pub fn batch_insert(&mut self, vectors: Vec<Vector>) -> Result<Vec<usize>>
Insert batch of vectors in parallel
Sourcepub fn rebuild_index(&mut self) -> Result<()>
pub fn rebuild_index(&mut self) -> Result<()>
Rebuild HNSW index from existing vectors
Sourcepub fn merge_from(&mut self, other: &VectorStore) -> Result<usize>
pub fn merge_from(&mut self, other: &VectorStore) -> Result<usize>
Merge another VectorStore into this one using IGTM algorithm
Sourcepub fn needs_index_rebuild(&self) -> bool
pub fn needs_index_rebuild(&self) -> bool
Check if index needs to be rebuilt
Sourcepub fn ensure_index_ready(&mut self) -> Result<()>
pub fn ensure_index_ready(&mut self) -> Result<()>
Ensure HNSW index is ready for search
Sourcepub fn knn_search(
&mut self,
query: &Vector,
k: usize,
) -> Result<Vec<(usize, f32)>>
pub fn knn_search( &mut self, query: &Vector, k: usize, ) -> Result<Vec<(usize, f32)>>
K-nearest neighbors search using HNSW
Sourcepub fn knn_search_with_ef(
&mut self,
query: &Vector,
k: usize,
ef: Option<usize>,
) -> Result<Vec<(usize, f32)>>
pub fn knn_search_with_ef( &mut self, query: &Vector, k: usize, ef: Option<usize>, ) -> Result<Vec<(usize, f32)>>
K-nearest neighbors search with optional ef override
Sourcepub fn knn_search_readonly(
&self,
query: &Vector,
k: usize,
ef: Option<usize>,
) -> Result<Vec<(usize, f32)>>
pub fn knn_search_readonly( &self, query: &Vector, k: usize, ef: Option<usize>, ) -> Result<Vec<(usize, f32)>>
Read-only K-nearest neighbors search (for parallel execution)
Sourcepub fn knn_search_ef(
&self,
query: &Vector,
k: usize,
ef: usize,
) -> Result<Vec<(usize, f32)>>
pub fn knn_search_ef( &self, query: &Vector, k: usize, ef: usize, ) -> Result<Vec<(usize, f32)>>
Fast K-nearest neighbors search with concrete ef value
Sourcepub fn knn_search_with_filter(
&mut self,
query: &Vector,
k: usize,
filter: &MetadataFilter,
) -> Result<Vec<(usize, f32, JsonValue)>>
pub fn knn_search_with_filter( &mut self, query: &Vector, k: usize, filter: &MetadataFilter, ) -> Result<Vec<(usize, f32, JsonValue)>>
K-nearest neighbors search with metadata filtering
Sourcepub fn knn_search_with_filter_ef(
&mut self,
query: &Vector,
k: usize,
filter: &MetadataFilter,
ef: Option<usize>,
) -> Result<Vec<(usize, f32, JsonValue)>>
pub fn knn_search_with_filter_ef( &mut self, query: &Vector, k: usize, filter: &MetadataFilter, ef: Option<usize>, ) -> Result<Vec<(usize, f32, JsonValue)>>
K-nearest neighbors search with metadata filtering and optional ef override
Sourcepub fn knn_search_with_filter_ef_readonly(
&self,
query: &Vector,
k: usize,
filter: &MetadataFilter,
ef: Option<usize>,
) -> Result<Vec<(usize, f32, JsonValue)>>
pub fn knn_search_with_filter_ef_readonly( &self, query: &Vector, k: usize, filter: &MetadataFilter, ef: Option<usize>, ) -> Result<Vec<(usize, f32, JsonValue)>>
Read-only filtered search (for parallel execution)
Uses Roaring bitmap index for O(1) filter evaluation when possible, falls back to JSON-based filtering for complex filters.
Sourcepub fn search(
&mut self,
query: &Vector,
k: usize,
filter: Option<&MetadataFilter>,
) -> Result<Vec<(usize, f32, JsonValue)>>
pub fn search( &mut self, query: &Vector, k: usize, filter: Option<&MetadataFilter>, ) -> Result<Vec<(usize, f32, JsonValue)>>
Search with optional filter (convenience method)
Sourcepub fn search_with_ef(
&mut self,
query: &Vector,
k: usize,
filter: Option<&MetadataFilter>,
ef: Option<usize>,
) -> Result<Vec<(usize, f32, JsonValue)>>
pub fn search_with_ef( &mut self, query: &Vector, k: usize, filter: Option<&MetadataFilter>, ef: Option<usize>, ) -> Result<Vec<(usize, f32, JsonValue)>>
Search with optional filter and ef override
Sourcepub fn search_with_options(
&mut self,
query: &Vector,
k: usize,
filter: Option<&MetadataFilter>,
ef: Option<usize>,
max_distance: Option<f32>,
) -> Result<Vec<(usize, f32, JsonValue)>>
pub fn search_with_options( &mut self, query: &Vector, k: usize, filter: Option<&MetadataFilter>, ef: Option<usize>, max_distance: Option<f32>, ) -> Result<Vec<(usize, f32, JsonValue)>>
Search with all options: filter, ef override, and max_distance
Sourcepub fn search_with_ef_readonly(
&self,
query: &Vector,
k: usize,
filter: Option<&MetadataFilter>,
ef: Option<usize>,
) -> Result<Vec<(usize, f32, JsonValue)>>
pub fn search_with_ef_readonly( &self, query: &Vector, k: usize, filter: Option<&MetadataFilter>, ef: Option<usize>, ) -> Result<Vec<(usize, f32, JsonValue)>>
Read-only search with optional filter (for parallel execution)
Sourcepub fn search_with_options_readonly(
&self,
query: &Vector,
k: usize,
filter: Option<&MetadataFilter>,
ef: Option<usize>,
max_distance: Option<f32>,
) -> Result<Vec<(usize, f32, JsonValue)>>
pub fn search_with_options_readonly( &self, query: &Vector, k: usize, filter: Option<&MetadataFilter>, ef: Option<usize>, max_distance: Option<f32>, ) -> Result<Vec<(usize, f32, JsonValue)>>
Read-only search with all options (for parallel execution)
Sourcepub fn search_batch(
&self,
queries: &[Vector],
k: usize,
ef: Option<usize>,
) -> Vec<Result<Vec<(usize, f32)>>> ⓘ
pub fn search_batch( &self, queries: &[Vector], k: usize, ef: Option<usize>, ) -> Vec<Result<Vec<(usize, f32)>>> ⓘ
Parallel batch search for multiple queries
Sourcepub fn search_batch_with_metadata(
&self,
queries: &[Vector],
k: usize,
ef: Option<usize>,
) -> Vec<Result<Vec<(usize, f32, JsonValue)>>> ⓘ
pub fn search_batch_with_metadata( &self, queries: &[Vector], k: usize, ef: Option<usize>, ) -> Vec<Result<Vec<(usize, f32, JsonValue)>>> ⓘ
Parallel batch search with metadata
Sourcepub fn knn_search_brute_force(
&self,
query: &Vector,
k: usize,
) -> Result<Vec<(usize, f32)>>
pub fn knn_search_brute_force( &self, query: &Vector, k: usize, ) -> Result<Vec<(usize, f32)>>
Brute-force K-NN search (fallback)
Sourcepub fn optimize(&mut self) -> Result<usize>
pub fn optimize(&mut self) -> Result<usize>
Optimize index for cache-efficient search
Reorders graph nodes and vectors using BFS traversal to improve memory locality. Nodes that are frequently accessed together during search will be stored adjacently in memory, reducing cache misses and improving QPS.
Call this after loading/building the index and before querying for best results. Based on NeurIPS 2021 “Graph Reordering for Cache-Efficient Near Neighbor Search”.
Returns the number of nodes reordered, or 0 if index is empty/not initialized.
Sourcepub fn count(&self) -> usize
pub fn count(&self) -> usize
Count of vectors stored (excluding deleted vectors)
Alias for len() - preferred for database-style APIs.
Sourcepub fn ids(&self) -> Vec<String>
pub fn ids(&self) -> Vec<String>
List all non-deleted IDs
Returns vector IDs without loading vector data. O(n) time, O(n) memory for strings only.
Sourcepub fn items(&self) -> Vec<(String, Vec<f32>, JsonValue)>
pub fn items(&self) -> Vec<(String, Vec<f32>, JsonValue)>
Get all items as (id, vector, metadata) tuples
Returns all non-deleted items. O(n) time and memory.
Sourcepub fn memory_usage(&self) -> usize
pub fn memory_usage(&self) -> usize
Memory usage estimate (bytes)
Sourcepub fn bytes_per_vector(&self) -> f32
pub fn bytes_per_vector(&self) -> f32
Bytes per vector (average)
Sourcepub fn set_ef_search(&mut self, ef_search: usize)
pub fn set_ef_search(&mut self, ef_search: usize)
Set HNSW ef_search parameter (runtime tuning)
Sourcepub fn get_ef_search(&self) -> Option<usize>
pub fn get_ef_search(&self) -> Option<usize>
Get HNSW ef_search parameter
Sourcepub fn flush(&mut self) -> Result<()>
pub fn flush(&mut self) -> Result<()>
Flush all pending changes to disk
Commits vector/metadata changes and HNSW index to .omen storage.
Sourcepub fn is_persistent(&self) -> bool
pub fn is_persistent(&self) -> bool
Check if this store has persistent storage enabled
Auto Trait Implementations§
impl Freeze for VectorStore
impl !RefUnwindSafe for VectorStore
impl Send for VectorStore
impl Sync for VectorStore
impl Unpin for VectorStore
impl !UnwindSafe for VectorStore
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
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
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 more