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