Repository navigation
Expand file tree
/
Copy pathquickstart.cpp
More file actions
105 lines (90 loc) · 4.21 KB
/
Copy pathquickstart.cpp
File metadata and controls
105 lines (90 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Quick-start: the smallest end-to-end use of the Engine API.
//
// Insert a few vectors with rich, typed metadata, run a plain nearest-neighbour
// search and a metadata-filtered one, then round-trip through persistence
// (snapshot + recover) -- the C++ equivalent of a vector-database "hello world".
#include <filesystem>
#include <iostream>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>
#include "toyvdb/engine.hpp"
using namespace toyvdb;
namespace {
// Render any metadata value (string / int64 / double / bool) as text.
std::string to_text(const MetaValue& v) {
return std::visit(
[](const auto& x) -> std::string {
using T = std::decay_t<decltype(x)>;
if constexpr (std::is_same_v<T, std::string>) return x;
else if constexpr (std::is_same_v<T, bool>) return x ? "true" : "false";
else return std::to_string(x);
},
v);
}
// Print one hit: external id, distance, and its full metadata map.
void print_hit(const Engine& db, const SearchResult& r) {
std::cout << " " << db.store().external_id(r.id) << " score=" << r.score;
if (const Metadata* m = db.store().metadata(r.id)) {
std::cout << " {";
bool first = true;
for (const auto& [key, val] : *m) {
std::cout << (first ? "" : ", ") << key << "=" << to_text(val);
first = false;
}
std::cout << "}";
}
std::cout << "\n";
}
} // namespace
int main() {
// A fresh directory so the demo is deterministic on repeated runs.
const std::filesystem::path dir = std::filesystem::temp_directory_path() / "toyvdb_quickstart";
std::filesystem::remove_all(dir);
std::filesystem::create_directories(dir);
EngineConfig cfg;
cfg.dim = 4;
cfg.metric = MetricKind::Cosine;
cfg.index = IndexKind::Hnsw;
cfg.hnsw = HnswParams{.M = 16, .efSearch = 50};
cfg.persistence = PersistenceConfig{dir}; // durable: every write is logged
Engine db(cfg);
// Metadata is a typed key -> value map: string / int64 / double / bool.
// Use std::int64_t{...} for integers so the variant picks the int alternative.
db.insert("cat", std::vector<float>{0.10f, 0.20f, 0.30f, 0.40f},
Metadata{{"species", std::string("feline")},
{"legs", std::int64_t{4}},
{"weight_kg", 4.5},
{"domesticated", true}});
db.insert("dog", std::vector<float>{0.12f, 0.18f, 0.32f, 0.38f},
Metadata{{"species", std::string("canine")},
{"legs", std::int64_t{4}},
{"weight_kg", 12.0},
{"domesticated", true}});
db.insert("spider", std::vector<float>{0.90f, 0.10f, 0.05f, 0.20f},
Metadata{{"species", std::string("arachnid")},
{"legs", std::int64_t{8}},
{"weight_kg", 0.001},
{"domesticated", false}});
db.insert("hawk", std::vector<float>{0.40f, 0.30f, 0.20f, 0.10f},
Metadata{{"species", std::string("raptor")},
{"legs", std::int64_t{2}},
{"weight_kg", 1.2},
{"domesticated", false}});
const std::vector<float> query{0.1f, 0.2f, 0.3f, 0.4f};
std::cout << "nearest neighbours (smaller score = closer):\n";
for (const auto& r : db.search(query, /*k=*/5)) print_hit(db, r);
// Metadata-filtered search: only domesticated animals with at most 4 legs.
// The Engine resolves the filter to an allowed-set and the index honours it.
const Filter f = Filter::all_of({Filter::eq("domesticated", true),
Filter::le("legs", std::int64_t{4})});
std::cout << "\nfiltered (domesticated AND legs <= 4):\n";
for (const auto& r : db.search(query, /*k=*/5, &f)) print_hit(db, r);
// Persist to a snapshot, then recover into a brand-new Engine -- our
// equivalent of save() / load(). The constructor replays the snapshot + WAL.
db.snapshot();
Engine reloaded(cfg);
std::cout << "\nreloaded " << reloaded.store().size() << " vectors from " << dir << "\n";
return 0;
}