1use recern_vector::{CollectionConfig, Database, Filter, Metric, RecallOptions, SearchOptions};
7use serde_json::json;
8
9fn main() -> recern_vector::Result<()> {
10 let path = std::env::temp_dir().join("recern-vector-quickstart.rvec");
11 let _ = std::fs::remove_file(&path);
12
13 let mut db = Database::create(&path)?;
14 let docs = db.create_collection("docs", CollectionConfig::new(32, Metric::Cosine))?;
15
16 let records: Vec<_> = (0..10_000)
18 .map(|i| {
19 let vector: Vec<f32> = (0..32).map(|d| pseudo_random(i * 32 + d)).collect();
20 let lang = ["en", "de", "fr"][i % 3];
21 (
22 format!("doc-{i}"),
23 vector,
24 Some(json!({"lang": lang, "year": 2015 + i % 10})),
25 )
26 })
27 .collect();
28 let query = records[42].1.clone();
29 docs.upsert_many(records)?;
30 println!("{} records", docs.len());
31
32 let filter = Filter::from_json(&json!({"lang": "en", "year": {"$gte": 2020}}))?;
34 let _same = Filter::And(vec![
36 Filter::eq("lang", "en"),
37 Filter::between("year", Some(2020.0), None),
38 ]);
39 let report = docs.explain(&query, 3, &SearchOptions::default().filter(filter))?;
40 for hit in &report.hits {
41 println!(
42 " {:<10} distance={:.4} {}",
43 hit.id,
44 hit.distance,
45 hit.metadata.as_ref().unwrap()
46 );
47 }
48 println!(
49 "strategy={} visited={} selectivity={:.1}% time={:?}",
50 report.strategy,
51 report.visited,
52 report.filter_selectivity.unwrap_or(1.0) * 100.0,
53 report.elapsed
54 );
55
56 let stats = docs.stats();
58 println!(
59 "layers={:?} unreachable={}",
60 stats.nodes_per_layer, stats.unreachable
61 );
62 let recall = docs.estimate_recall(&RecallOptions {
63 ef_values: vec![16, 64],
64 ..Default::default()
65 })?;
66 for point in &recall.points {
67 println!(
68 " ef={:<3} recall@{}={:.3}",
69 point.ef, recall.k, point.recall
70 );
71 }
72
73 db.save()?;
74 let reopened = Database::open(&path)?;
75 println!("reopened: {} records", reopened.collection("docs")?.len());
76 Ok(())
77}
78
79fn pseudo_random(seed: usize) -> f32 {
81 let mut x = seed as u64 ^ 0x9E37_79B9_7F4A_7C15;
82 x = (x ^ (x >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
83 x = (x ^ (x >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
84 ((x ^ (x >> 31)) as f64 / u64::MAX as f64 * 2.0 - 1.0) as f32
85}