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

Method search

nodedb-vector/src/ivf.rs:130–189  ·  view source on GitHub ↗

Search: find top-k nearest neighbors.

(&self, query: &[f32], top_k: usize)

Source from the content-addressed store, hash-verified

128
129 /// Search: find top-k nearest neighbors.
130 pub fn search(&self, query: &[f32], top_k: usize) -> Vec<SearchResult> {
131 assert_eq!(query.len(), self.dim);
132 if self.centroids.is_empty() || self.count == 0 {
133 return Vec::new();
134 }
135
136 let pq = match &self.pq {
137 Some(p) => p,
138 None => return Vec::new(),
139 };
140
141 let nprobe = self.params.nprobe.min(self.centroids.len());
142 let mut centroid_dists: Vec<(usize, f32)> = self
143 .centroids
144 .iter()
145 .enumerate()
146 .map(|(i, c)| (i, distance(query, c, self.params.metric)))
147 .collect();
148 centroid_dists.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
149
150 let mut candidates: Vec<SearchResult> = Vec::new();
151
152 for &(cell_idx, _) in centroid_dists.iter().take(nprobe) {
153 let residual_query: Vec<f32> = query
154 .iter()
155 .zip(&self.centroids[cell_idx])
156 .map(|(q, c)| q - c)
157 .collect();
158 let table = match pq.build_distance_table(&residual_query) {
159 Ok(t) => t,
160 Err(e) => {
161 tracing::warn!(error = %e, "IVF PQ build_distance_table budget exhausted; skipping cell");
162 continue;
163 }
164 };
165
166 for (id, code) in &self.cells[cell_idx] {
167 let dist = pq.asymmetric_distance(&table, code);
168 candidates.push(SearchResult {
169 id: *id,
170 distance: dist,
171 });
172 }
173 }
174
175 if candidates.len() > top_k {
176 candidates.select_nth_unstable_by(top_k, |a, b| {
177 a.distance
178 .partial_cmp(&b.distance)
179 .unwrap_or(std::cmp::Ordering::Equal)
180 });
181 candidates.truncate(top_k);
182 }
183 candidates.sort_by(|a, b| {
184 a.distance
185 .partial_cmp(&b.distance)
186 .unwrap_or(std::cmp::Ordering::Equal)
187 });

Calls 11

collectMethod · 0.80
build_distance_tableMethod · 0.80
asymmetric_distanceMethod · 0.80
distanceFunction · 0.50
is_emptyMethod · 0.45
lenMethod · 0.45
iterMethod · 0.45
partial_cmpMethod · 0.45
takeMethod · 0.45
pushMethod · 0.45
truncateMethod · 0.45