Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions crates/ruvector-router-core/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@ impl HnswIndex {
}

// Find nearest neighbors (safe now - no locks held)
let neighbors =
self.search_knn_internal(&vector, self.config.ef_construction.min(self.config.m * 2));
let neighbors = self.search_knn_internal(&vector, self.config.ef_construction);

// Re-acquire graph lock for modifications
let mut graph = self.graph.write();
Expand Down Expand Up @@ -187,7 +186,7 @@ impl HnswIndex {
let entry_id = entry_point.as_ref().unwrap();
let mut visited = HashSet::new();
let mut candidates = BinaryHeap::new();
let mut result = BinaryHeap::new();
let mut result: BinaryHeap<std::cmp::Reverse<Neighbor>> = BinaryHeap::new();

// Calculate distance to entry point
if let Some(entry_vec) = vectors.get(entry_id) {
Expand All @@ -199,14 +198,14 @@ impl HnswIndex {
};

candidates.push(neighbor.clone());
result.push(neighbor);
result.push(std::cmp::Reverse(neighbor));
visited.insert(entry_id.clone());
}

// Search phase
while let Some(current) = candidates.pop() {
// Check if we should continue
if let Some(furthest) = result.peek() {
if let Some(std::cmp::Reverse(furthest)) = result.peek() {
if current.distance > furthest.distance && result.len() >= ef {
break;
}
Expand Down Expand Up @@ -235,11 +234,11 @@ impl HnswIndex {

// Add to results if better than current worst
if result.len() < ef {
result.push(neighbor);
} else if let Some(worst) = result.peek() {
result.push(std::cmp::Reverse(neighbor));
} else if let Some(std::cmp::Reverse(worst)) = result.peek() {
if dist < worst.distance {
result.pop();
result.push(neighbor);
result.push(std::cmp::Reverse(neighbor));
}
}
}
Expand All @@ -248,7 +247,7 @@ impl HnswIndex {
}

// Convert to sorted vector
let mut sorted_results: Vec<Neighbor> = result.into_iter().collect();
let mut sorted_results: Vec<Neighbor> = result.into_iter().map(|r| r.0).collect();
sorted_results.sort_by(|a, b| {
a.distance
.partial_cmp(&b.distance)
Expand Down
16 changes: 14 additions & 2 deletions crates/ruvector-router-core/src/vector_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,20 @@ impl VectorDB {

let index = Arc::new(HnswIndex::new(hnsw_config));

let stats = Arc::new(RwLock::new(VectorDbStats {
total_vectors: 0,
// Rebuild index from persisted vectors (fixes search returning 0 results after restart)
let stored_ids = storage.get_all_ids()?;
if !stored_ids.is_empty() {
let mut entries = Vec::with_capacity(stored_ids.len());
for id in &stored_ids {
if let Some(vector) = storage.get(id)? {
entries.push((id.clone(), vector));
}
}
index.insert_batch(entries)?;
}

let stats = Arc::new(RwLock::new(VectorDbStats {
total_vectors: stored_ids.len(),
index_size_bytes: 0,
storage_size_bytes: 0,
avg_query_latency_us: 0.0,
Expand Down