Skip to main content

velesdb_core/collection/vector_collection/
crud.rs

1//! CRUD and index-mutation operations for `VectorCollection`.
2
3use crate::error::Result;
4use crate::point::Point;
5
6use super::VectorCollection;
7
8impl VectorCollection {
9    /// Bulk insert optimized for high-throughput import.
10    ///
11    /// # Errors
12    ///
13    /// Returns an error if any point has a mismatched dimension.
14    pub fn upsert_bulk(&self, points: &[Point]) -> Result<usize> {
15        self.inner.upsert_bulk(points)
16    }
17
18    /// Bulk insert from contiguous flat slices (zero-copy from numpy / FFI).
19    ///
20    /// Accepts a flat `f32` slice of shape `(n, dimension)` in row-major order
21    /// plus a matching `u64` ID slice of length `n`. Avoids per-row `Vec<f32>`
22    /// allocation, saving ~293 MB for 100K vectors at 768D.
23    ///
24    /// # Errors
25    ///
26    /// - Returns [`crate::error::Error::InvalidVector`] if `vectors.len() != ids.len() * dimension`.
27    /// - Returns [`crate::error::Error::DimensionMismatch`] if `dimension` mismatches the collection.
28    pub fn upsert_bulk_from_raw(
29        &self,
30        vectors: &[f32],
31        ids: &[u64],
32        dimension: usize,
33        payloads: Option<&[Option<serde_json::Value>]>,
34    ) -> Result<usize> {
35        self.inner
36            .upsert_bulk_from_raw(vectors, ids, dimension, payloads)
37    }
38
39    /// Inserts or updates points in the collection.
40    ///
41    /// # Errors
42    ///
43    /// - Returns an error if any point's dimension does not match the collection.
44    /// - Returns an error if storage operations fail.
45    ///
46    /// # Examples
47    ///
48    /// ```rust,no_run
49    /// # use velesdb_core::{VectorCollection, DistanceMetric, Point, StorageMode};
50    /// # use serde_json::json;
51    /// # let coll = VectorCollection::create("./data/v".into(), "v", 128, DistanceMetric::Cosine, StorageMode::Full)?;
52    /// coll.upsert(vec![
53    ///     Point::new(1, vec![0.1; 128], Some(json!({"title": "Hello"}))),
54    ///     Point::new(2, vec![0.2; 128], None),
55    /// ])?;
56    /// # Ok::<(), velesdb_core::Error>(())
57    /// ```
58    pub fn upsert(&self, points: impl IntoIterator<Item = Point>) -> Result<()> {
59        self.inner.upsert(points)
60    }
61
62    /// Retrieves points by IDs, returning `None` for missing entries.
63    ///
64    /// # Examples
65    ///
66    /// ```rust,no_run
67    /// # use velesdb_core::{VectorCollection, DistanceMetric, StorageMode};
68    /// # let coll = VectorCollection::create("./data/v".into(), "v", 128, DistanceMetric::Cosine, StorageMode::Full)?;
69    /// let points = coll.get(&[1, 2, 3]);
70    /// for (id, maybe_point) in [1, 2, 3].iter().zip(&points) {
71    ///     if let Some(p) = maybe_point {
72    ///         println!("Found point {id} with payload {:?}", p.payload);
73    ///     }
74    /// }
75    /// # Ok::<(), velesdb_core::Error>(())
76    /// ```
77    #[must_use]
78    pub fn get(&self, ids: &[u64]) -> Vec<Option<Point>> {
79        self.inner.get(ids)
80    }
81
82    /// Deletes points by IDs.
83    ///
84    /// Missing IDs are silently ignored.
85    ///
86    /// # Errors
87    ///
88    /// - Returns an error if storage operations fail.
89    ///
90    /// # Examples
91    ///
92    /// ```rust,no_run
93    /// # use velesdb_core::{VectorCollection, DistanceMetric, StorageMode};
94    /// # let coll = VectorCollection::create("./data/v".into(), "v", 128, DistanceMetric::Cosine, StorageMode::Full)?;
95    /// coll.delete(&[1, 2, 3])?;
96    /// # Ok::<(), velesdb_core::Error>(())
97    /// ```
98    pub fn delete(&self, ids: &[u64]) -> Result<()> {
99        self.inner.delete(ids)
100    }
101
102    /// Inserts or updates metadata-only points (no vectors).
103    ///
104    /// # Errors
105    ///
106    /// - Returns an error if storage operations fail.
107    pub fn upsert_metadata(
108        &self,
109        points: impl IntoIterator<Item = crate::point::Point>,
110    ) -> Result<()> {
111        self.inner.upsert_metadata(points)
112    }
113
114    /// Creates a secondary metadata index on a payload field.
115    ///
116    /// # Errors
117    ///
118    /// - Returns an error if the index already exists or storage fails.
119    pub fn create_index(&self, field: &str) -> Result<()> {
120        self.inner.create_index(field)
121    }
122
123    /// Creates a property index for O(1) equality lookups.
124    ///
125    /// # Errors
126    ///
127    /// - Returns an error if the index already exists or storage fails.
128    pub fn create_property_index(&self, label: &str, property: &str) -> Result<()> {
129        self.inner.create_property_index(label, property)
130    }
131
132    /// Creates a range index for O(log n) range queries.
133    ///
134    /// # Errors
135    ///
136    /// - Returns an error if the index already exists or storage fails.
137    pub fn create_range_index(&self, label: &str, property: &str) -> Result<()> {
138        self.inner.create_range_index(label, property)
139    }
140
141    /// Drops an index, returning `true` if an index was removed.
142    ///
143    /// # Errors
144    ///
145    /// - Returns an error if the drop operation fails.
146    pub fn drop_index(&self, label: &str, property: &str) -> Result<bool> {
147        self.inner.drop_index(label, property)
148    }
149
150    /// Adds a graph edge to the collection.
151    ///
152    /// # Errors
153    ///
154    /// Returns an error if the edge cannot be stored.
155    pub fn add_edge(&self, edge: crate::collection::GraphEdge) -> Result<()> {
156        self.inner.add_edge(edge)
157    }
158}