pub enum Filter {
Eq {
field: String,
value: Value,
},
In {
field: String,
values: Vec<Value>,
},
Range {
field: String,
gt: Option<f64>,
gte: Option<f64>,
lt: Option<f64>,
lte: Option<f64>,
},
And(Vec<Filter>),
}Expand description
Metadata predicate applied during search.
Fields are addressed by dotted paths ("source.lang"). A record without
the field never matches.
Variants§
Implementations§
Source§impl Filter
impl Filter
Sourcepub fn eq(field: impl Into<String>, value: impl Into<Value>) -> Self
pub fn eq(field: impl Into<String>, value: impl Into<Value>) -> Self
Examples found in repository?
examples/quickstart.rs (line 36)
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 // Batch insert: (id, vector, metadata). Built on all cores, atomic.
17 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 // Search with a filter; explain() returns the hits and how they were found.
33 let filter = Filter::from_json(&json!({"lang": "en", "year": {"$gte": 2020}}))?;
34 // The same filter, built in code:
35 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 // Index health and recall against exact search.
57 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}pub fn is_in( field: impl Into<String>, values: impl IntoIterator<Item = Value>, ) -> Self
Sourcepub fn between(
field: impl Into<String>,
gte: Option<f64>,
lte: Option<f64>,
) -> Self
pub fn between( field: impl Into<String>, gte: Option<f64>, lte: Option<f64>, ) -> Self
Inclusive range. Either bound may be omitted.
Examples found in repository?
examples/quickstart.rs (line 37)
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 // Batch insert: (id, vector, metadata). Built on all cores, atomic.
17 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 // Search with a filter; explain() returns the hits and how they were found.
33 let filter = Filter::from_json(&json!({"lang": "en", "year": {"$gte": 2020}}))?;
34 // The same filter, built in code:
35 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 // Index health and recall against exact search.
57 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}pub fn matches(&self, metadata: Option<&Value>) -> bool
Sourcepub fn from_json(value: &Value) -> Result<Self>
pub fn from_json(value: &Value) -> Result<Self>
Parses a MongoDB-style filter:
{"lang": "en", "year": {"$gte": 2020, "$lt": 2025}, "tag": {"$in": ["a", "b"]}}Top-level keys are combined with AND. Supported operators: $eq,
$in, $gt, $gte, $lt, $lte.
Examples found in repository?
examples/quickstart.rs (line 33)
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 // Batch insert: (id, vector, metadata). Built on all cores, atomic.
17 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 // Search with a filter; explain() returns the hits and how they were found.
33 let filter = Filter::from_json(&json!({"lang": "en", "year": {"$gte": 2020}}))?;
34 // The same filter, built in code:
35 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 // Index health and recall against exact search.
57 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}Trait Implementations§
impl StructuralPartialEq for Filter
Auto Trait Implementations§
impl Freeze for Filter
impl RefUnwindSafe for Filter
impl Send for Filter
impl Sync for Filter
impl Unpin for Filter
impl UnsafeUnpin for Filter
impl UnwindSafe for Filter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more