Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Search Request & Filters

This page covers the types that describe how to search: the unified SearchRequest, the filtering primitives Filter and Bitset, and the IteratorContext used for incremental search. The deprecated SearchParam is documented at the end for migration.

SearchRequest

Declared in vsag/search_request.h. SearchRequest is a plain struct that bundles every option for Index::SearchWithRequest. Fill in the fields you need and leave the rest at their defaults.

vsag::SearchRequest request;
request.query_ = query;      // DatasetPtr with one query vector
request.mode_ = vsag::SearchMode::KNN_SEARCH;
request.topk_ = 10;
request.params_str_ = R"({"hgraph": {"ef_search": 100}})";

auto result = index->SearchWithRequest(request);

SearchMode

enum class SearchMode {
    KNN_SEARCH = 1,    // return the top-k nearest vectors
    RANGE_SEARCH = 2,  // return all vectors within radius_
};

Basic fields

FieldTypeDefaultMeaning
query_DatasetPtrnullptrThe query. IVF KNN requests support multiple query vectors; other requests allow one.
mode_SearchModeKNN_SEARCHKNN vs. range search.
topk_int64_t10Neighbors to return (KNN mode). Must be positive.
radius_float0.5Distance threshold (range mode). Non-negative.
limited_size_int64_t-1Cap on range results; -1 means no limit.
params_str_std::string""Algorithm-specific search params as JSON (e.g. ef_search).

Custom query distance callback

distance_batch_func_ optionally supplies query-to-vector scores from application code. It receives stable external vector IDs, so a closure can keep the query and query-specific state outside VSAG:

request.distance_batch_size_ = 32;
request.distance_batch_func_ = [query](const int64_t* ids, uint64_t count, float* scores) {
    for (uint64_t i = 0; i < count; ++i) {
        scores[i] = Score(query, ids[i]);
    }
};
FieldTypeDefaultMeaning
distance_batch_func_SearchDistanceBatchFuncnullptrFills one score for each input external ID, in input order. Smaller finite scores are better.
distance_batch_size_uint64_t1Maximum IDs passed to one callback invocation. Set this to the scorer’s efficient batch width for batched inference or external data access. Must be positive when a callback is set.

The callback is request-scoped and is not serialized. It may capture the query. hgraph permits a null query_ in callback mode, while ivf still requires one query vector for bucket routing. The callback must be stable for one request, thread-safe if the caller enables parallel execution, non-throwing, and must write only finite scores.

brute_force uses the callback for exact KNN and range search. hgraph supports KNN only; the callback drives graph traversal and final ordering, while the graph remains built with its configured built-in metric. Therefore recall under the callback score is not guaranteed. HGraph may score filtered traversal nodes to preserve graph connectivity, but filtered nodes are never returned. Callback HGraph does not support parallel search or brute_force_threshold; those configurations are rejected rather than silently changing search semantics.

ivf supports callback KNN with a non-null single query vector. IVF uses its configured built-in metric to select scan_buckets_count buckets, then applies the callback to candidates in those buckets. The callback controls candidate ranking but cannot recover vectors outside the selected buckets; increase scan_buckets_count to improve recall. Callback IVF does not support range search, disable_bucket_scan, bucket-graph search, or parallel search. Those configurations are rejected. Reordering is automatically disabled in callback mode. Other indexes do not support the callback.

IVF bucket routing

IVF accepts {"ivf":{"scan_buckets_count":N,"disable_bucket_scan":true}} through params_str_. This routing-only mode returns the N selected bucket IDs per query in the result Dataset instead of vector labels. NumElements() equals the number of queries, Dim() equals scan_buckets_count, GetIds() contains bucket IDs (with -1 for empty slots), and GetDistances() has distances to bucket centroids. No vector scan is performed, so filters, topk, range limits, reordering, and reasoning options are ignored.

IVF bucket IDs bypass

The bucket_ids_ field allows callers to provide pre-selected bucket IDs, bypassing IVF’s internal bucket routing (ClassifyDatasForSearch). When non-empty, the search skips centroid-based selection and scans only the specified buckets.

FieldTypeDefaultMeaning
bucket_ids_std::vector<std::vector<int64_t>>{}Pre-selected bucket IDs for bypassing IVF routing.

Semantics:

  • Empty (default): Use normal bucket routing via ClassifyDatasForSearch.
  • Non-empty: Skip routing and scan only the provided bucket IDs.
  • Batch IVF KNN: One outer bucket_ids_ entry per query vector. Result is rectangular: NumElements() is query count, Dim() is topk_. Missing neighbors are -1 with infinite distance.

Constraints:

  • Batch IVF search supports KNN only; custom query distance and reasoning labels are unsupported.
  • A non-empty outer vector must contain exactly one non-empty entry per query vector.
  • Each bucket ID must be in range [0, bucket_count).
  • Duplicate bucket IDs are rejected.
  • Incompatible with disable_bucket_scan mode.
  • Caller is responsible for ordering bucket IDs (no automatic sorting).

Filtering fields

Three filtering mechanisms are available and are combined with logical AND when more than one is enabled.

FieldTypeDefaultMeaning
enable_attribute_filter_boolfalseEnable SQL-style attribute filtering.
attribute_filter_str_std::string""The filter expression (see below). Requires enable_attribute_filter_.
enable_filter_boolfalseEnable a custom Filter callback.
filter_FilterPtrnullptrThe filter object. Requires enable_filter_.
enable_bitset_filter_boolfalseEnable a Bitset filter.
bitset_filter_BitsetPtrnullptrThe bitset. Test(id) == true excludes id. Requires enable_bitset_filter_.

The attribute_filter_str_ grammar is SQL-like. Examples:

category = 'electronics' AND price != 1000
multi_in(category, ['electronics', 'clothing']) AND multi_notin(color, ['red', 'blue'])

See Attribute Filter (Hybrid Search) and Filtered Search.

Resource & iterator fields

FieldTypeDefaultMeaning
search_allocator_Allocator*nullptrPer-search allocator; falls back to the index allocator when null.
enable_iterator_search_boolfalseEnable incremental (iterator) search.
p_iter_ctx_IteratorContext**nullptrHandle to the iterator state, reused across calls.
is_last_search_boolfalseMarks the final call of an iterator sequence.
expected_labels_std::vector<int64_t>{}Ids expected in the result; enables reasoning analysis of missed recalls.

See Per-Search Allocator and Iterator Search, plus examples/cpp/313/314 for the allocator.

Filter

Declared in vsag/filter.h. Implement this abstract class to express arbitrary “keep this id?” logic. Hold it through FilterPtr (std::shared_ptr<Filter>).

class Filter {
public:
    enum class Distribution { NONE = 0, RELATED_TO_VECTOR };

    virtual bool CheckValid(int64_t id) const = 0;          // true  => KEEP the id
    virtual bool CheckValid(const char* data) const;         // extra-info variant (default true)
    virtual float ValidRatio() const;                        // fraction kept (default 1.0)
    virtual Distribution FilterDistribution() const;         // hint (default NONE)
    virtual void GetValidIds(const int64_t** valid_ids, int64_t& count) const;
};

Convention: Filter::CheckValid(id) returns true to keep a vector. This is the opposite of the bitset / std::function<bool(int64_t)> pre-filter overloads on Index, where true means filtered out. Keep this distinction in mind when choosing an overload.

MemberPurpose
CheckValid(int64_t id)Core predicate. true keeps the id in results.
CheckValid(const char* data)Predicate over an element’s extra-info bytes. Defaults to true.
ValidRatio()Estimated fraction of vectors that pass; lets the engine pick a strategy.
FilterDistribution()RELATED_TO_VECTOR hints validity correlates with vector position.
GetValidIds(...)Optionally expose the explicit valid-id set.

See examples/cpp/301_feature_filter.cpp.

Bitset

Declared in vsag/bitset.h. A compact set of bit flags keyed by position, held through BitsetPtr. It is used both as a filtering input and as a utility (e.g. the result of l2_and_filtering).

static BitsetPtr Random(int64_t length);  // random bitset of the given length
static BitsetPtr Make();                  // empty bitset

void Set(int64_t pos, bool value);
void Set(int64_t pos);       // = Set(pos, true)
bool Test(int64_t pos) const;
uint64_t Count();            // number of set bits
std::string Dump();          // debug dump

When a Bitset is used as a search pre-filter (bitset_filter_, or the invalid argument of KnnSearch / RangeSearch), Test(id) == true means the id is filtered out.

IteratorContext

Declared in vsag/iterator_context.h. An opaque handle that stores the position of an in-progress iterator search so that subsequent calls resume where the previous one stopped.

class IteratorContext {
public:
    virtual ~IteratorContext() = default;
};

You do not construct or inspect it directly. VSAG allocates it on the first iterator search; pass the same handle back (via SearchRequest::p_iter_ctx_, or the KnnSearch iterator overload) on each subsequent call, and set the last-search flag on the final call so the engine can release it. See Iterator Search.

SearchParam (deprecated)

Declared in vsag/search_param.h. SearchParam predates SearchRequest and is retained only for the deprecated KnnSearch(query, k, SearchParam&) overload.

struct SearchParam {  // [[deprecated]] use SearchRequest
    bool is_iter_filter{false};
    bool is_last_search{false};
    const std::string& parameters;
    FilterPtr filter{nullptr};
    Allocator* allocator{nullptr};
    IteratorContext* iter_ctx{nullptr};
};

Prefer SearchRequest + SearchWithRequest for all new code. SearchParam holds parameters by reference, so the referenced string must outlive the call.

See also

  • Index — the search methods that consume these types.
  • Dataset — building the query_ and reading results.
  • Auxiliary Types — attribute value types used by attribute filters.