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

Dataset

vsag::Dataset (declared in vsag/dataset.h) is the universal container VSAG uses for inputs (base vectors to build/add, query vectors to search) and outputs (search results, retrieved vectors). You always hold it through DatasetPtr:

using DatasetPtr = std::shared_ptr<Dataset>;

Builder pattern

Dataset uses a fluent builder: Make() creates an instance, and every setter returns the same DatasetPtr so calls chain. Setters only store pointers/values — they do not copy your buffers.

auto base = vsag::Dataset::Make()
                ->Dim(128)
                ->NumElements(10000)
                ->Ids(ids)                 // const int64_t*
                ->Float32Vectors(vectors)  // const float*
                ->Owner(false);            // caller keeps ownership of ids/vectors

Ownership

Ownership controls who frees the underlying buffers:

CallMeaning
Owner(true)The dataset owns its buffers and frees them on destruction (using the default allocator).
Owner(true, allocator)The dataset owns its buffers and frees them via the supplied Allocator.
Owner(false)The caller keeps ownership; the dataset only borrows the pointers. They must outlive the dataset.

Use Owner(false) for build/query inputs you already hold. Search results returned by the index use Owner(true), so you can read them and let the DatasetPtr free everything.

DatasetPtr Make();               // static factory

DatasetPtr Owner(bool is_owner, Allocator* allocator);
DatasetPtr Owner(bool is_owner);              // uses the default allocator
DatasetPtr Append(const DatasetPtr& other);   // concatenate another dataset
DatasetPtr DeepCopy(Allocator* allocator = nullptr) const;  // independent copy

Metadata

SetterGetterTypeMeaning
NumElements(int64_t)GetNumElements()int64_tNumber of elements (vectors/rows).
Dim(int64_t)GetDim()int64_tDense vector dimensionality.
Ids(const int64_t*)GetIds()const int64_t*Per-element ids (length NumElements).
Distances(const float*)GetDistances()const float*Distances (search output; length depends on k/matches).

Vector payloads

A dataset carries exactly one vector representation, chosen to match the index’s dtype:

SetterGetterElement typeUse with
Float32Vectors(const float*)GetFloat32Vectors()floatdtype: float32
Float16Vectors(const uint16_t*)GetFloat16Vectors()uint16_tdtype: float16 and bfloat16 (raw 16-bit payload)
Int8Vectors(const int8_t*)GetInt8Vectors()int8_tdtype: int8
SparseVectors(const SparseVector*)GetSparseVectors()SparseVectordtype: sparse (SINDI)

Dense vectors are laid out row-major: element i, dimension j lives at vectors[i * dim + j].

Multi-vector payloads

For documents that hold several dense sub-vectors each:

SetterGetterTypeMeaning
MultiVectors(const MultiVector*)GetMultiVectors()MultiVectorOne entry per document.
MultiVectorDim(int64_t)GetMultiVectorDim()int64_tFloats per sub-vector (independent of Dim).
VectorCounts(const uint32_t*)GetVectorCounts()const uint32_t*Sub-vector count per document.

Metadata payloads

SetterGetterTypeMeaning
AttributeSets(const AttributeSet*)GetAttributeSets()AttributeSetPer-element attributes for hybrid search.
ExtraInfos(const char*)GetExtraInfos()const char*Packed extra-info blobs.
ExtraInfoSize(int64_t)GetExtraInfoSize()int64_tBytes per extra-info blob.
Paths(const std::string*)GetPaths()const std::string*Hierarchy paths (Pyramid). Default hierarchy.
Paths(const std::string& hierarchy, const std::string*)GetPaths(const std::string& hierarchy)const std::string*Paths for a named hierarchy.
SourceID(const std::string*)GetSourceID()const std::string*Optional source identifier.

See Attribute Filter (Hybrid Search) and Extra Info.

Diagnostics payloads

SetterGetterTypeMeaning
Statistics(const std::string&)GetStatistics() / GetStatistics(keys)std::string / std::vector<std::string>Serialized statistics; the keyed getter returns values for the requested keys.
Reasoning(const std::string&)GetReasoning()std::stringReasoning report (JSON) explaining recall of expected_labels_.

Reading search results

Search methods return a DatasetPtr you read back with the getters:

auto result = index->KnnSearch(query, 10, search_params);
if (result.has_value()) {
    auto r = result.value();
    for (int64_t i = 0; i < r->GetDim(); ++i) {
        int64_t id = r->GetIds()[i];
        float dist = r->GetDistances()[i];
    }
}

For KNN, GetNumElements() is 1 and the ids/distances arrays have length k. For range search, the number of matches is reported through the result’s dimension. See k-Nearest Neighbor Search.

SparseVector

struct SparseVector {
    uint32_t len_ = 0;         // number of non-zero entries
    uint32_t* ids_ = nullptr;  // term ids, length len_ (sorted ascending inside the index)
    float* vals_ = nullptr;    // term weights, length len_

    // optional original tokenization (order/duplicates preserved, unlike ids_)
    uint32_t token_seq_len_ = 0;
    uint32_t* token_sequence_ = nullptr;
};

Sorting ids_ ascending before insertion is recommended. token_sequence_ is optional and only used by indexes that consume raw token order.

MultiVector

struct MultiVector {
    uint32_t len_ = 0;          // number of sub-vectors in this document
    float* vectors_ = nullptr;  // flat array of len_ * MultiVectorDim floats
};

When Owner(true) is set, each element’s vectors_ must be independently allocated, because the destructor frees each vectors_ separately.

See also