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
4 changes: 3 additions & 1 deletion bindings/c/include/svs/c/svs_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -1460,7 +1460,9 @@ SVS_API bool svs_index_get_size(
/// @details Performs a TopK search on the index with the provided queries and an optional
/// ID filter. The ID filter allows for filtering the search results based on specific IDs,
/// enabling more targeted searches. If the ID filter is NULL, the search will return the
/// top K results. If ID filter is provided, only the results that pass the filter will be
/// top K results, except that SVS_SYNC_KIND_FINE_GRAIN may return fewer when concurrent
/// consolidation removes selected IDs. Use the CSR offsets to determine each query's
/// result count. If ID filter is provided, only the results that pass the filter will be
/// returned. Results are written into @p out_results in CSR layout (see
/// svs_search_results); library-owned buffers are reused across calls when their
/// capacity suffices. If ID filter is provided with `filter_rate > 0.0` then the
Expand Down
23 changes: 22 additions & 1 deletion bindings/c/src/index_vamana.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "index_builder.hpp"

#include <svs/concepts/data.h>
#include <svs/concurrent/dynamic_index.h>
#include <svs/core/query_result.h>
#include <svs/lib/misc.h>
#include <svs/orchestrators/dynamic_vamana.h>
Expand Down Expand Up @@ -132,7 +133,27 @@ std::pair<svs::QueryResult<size_t>, std::vector<size_t>> DynamicIndexVamana::sea

if (id_filter == nullptr) {
index.search(results.view(), queries, params);
return {results, std::vector<size_t>(queries.size(), num_neighbors)};
auto found_neighbors_per_query = std::vector<size_t>(queries.size(), num_neighbors);
if (sync_kind == SVS_SYNC_KIND_FINE_GRAIN) {
// Consolidation can erase buffered IDs before translation. The CSR exporter
// consumes each row's counted prefix, so move IDs and distances together.
for (size_t i = 0; i < results.n_queries(); ++i) {
size_t found = 0;
for (size_t j = 0; j < results.n_neighbors(); ++j) {
const auto id = results.index(i, j);
if (id == svs::index::vamana::concurrent::no_external_id) {
continue;
}
if (found != j) {
results.index(i, found) = id;
results.distance(i, found) = results.distance(i, j);
}
++found;
}
found_neighbors_per_query[i] = found;
}
}
return {std::move(results), std::move(found_neighbors_per_query)};
}

std::mt19937 rng(42);
Expand Down
Loading