MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / insert

Method insert

nodedb-vector/src/hnsw/build.rs:19–101  ·  view source on GitHub ↗

Insert a vector into the index. 1. Assign a random layer using the exponential distribution 2. Greedily descend from the entry point to the new node's layer + 1 3. At each layer from the node's layer down to 0, search for nearest neighbors, select via the diversity heuristic, and add bidirectional edges 4. Prune over-connected nodes to maintain the M/M0 invariant

(&mut self, vector: Vec<f32>)

Source from the content-addressed store, hash-verified

17 /// neighbors, select via the diversity heuristic, and add bidirectional edges
18 /// 4. Prune over-connected nodes to maintain the M/M0 invariant
19 pub fn insert(&mut self, vector: Vec<f32>) -> Result<(), VectorError> {
20 // Materialize flat neighbor storage on first mutation.
21 self.ensure_mutable_neighbors();
22
23 if vector.len() != self.dim {
24 return Err(VectorError::DimensionMismatch {
25 expected: self.dim,
26 got: vector.len(),
27 });
28 }
29
30 let new_id = self.nodes.len() as u32;
31 let new_layer = self.random_layer();
32
33 let storage = match self.params.dtype {
34 VectorStorageDtype::F32 => NodeStorage::F32(vector.clone()),
35 dtype => NodeStorage::Bytes {
36 dtype,
37 bytes: cast_from_f32(&vector, dtype),
38 },
39 };
40 let node = Node {
41 storage,
42 neighbors: (0..=new_layer).map(|_| Vec::new()).collect(),
43 deleted: false,
44 };
45 self.nodes.push(node);
46
47 let Some(ep) = self.entry_point else {
48 self.entry_point = Some(new_id);
49 self.max_layer = new_layer;
50 return Ok(());
51 };
52
53 // Encode query once to the index dtype for all dist_to_node calls below.
54 let query = vector;
55 let query_bytes = cast_from_f32(&query, self.params.dtype);
56
57 let mut current_ep = ep;
58
59 // Phase 1: Greedy descent from top layer to new_layer + 1.
60 if self.max_layer > new_layer {
61 for layer in (new_layer + 1..=self.max_layer).rev() {
62 let results = search_layer(self, &query_bytes, current_ep, 1, layer, None, 0);
63 if let Some(nearest) = results.first() {
64 current_ep = nearest.id;
65 }
66 }
67 }
68
69 // Phase 2: Insert at each layer from min(new_layer, max_layer) down to 0.
70 let insert_top = new_layer.min(self.max_layer);
71 for layer in (0..=insert_top).rev() {
72 let ef = self.params.ef_construction;
73 let candidates = search_layer(self, &query_bytes, current_ep, ef, layer, None, 0);
74
75 let m = self.max_neighbors(layer);
76 let selected = select_neighbors_heuristic(self, &candidates, m);

Callers 15

make_inputFunction · 0.45
all_matching_returns_oneFunction · 0.45
unfiltered_search_layerFunction · 0.45
navix_search_layer_0Function · 0.45
expand_standardFunction · 0.45
expand_directedFunction · 0.45
expand_blindFunction · 0.45
build_indexFunction · 0.45
all_allowedFunction · 0.45

Calls 15

cast_from_f32Function · 0.85
search_layerFunction · 0.85
collectMethod · 0.80
firstMethod · 0.80
lenMethod · 0.45
random_layerMethod · 0.45
cloneMethod · 0.45
pushMethod · 0.45
max_neighborsMethod · 0.45
iterMethod · 0.45