Skip to main content

nitrite_vector/
fluent.rs

1//! Fluent API for building vector search filters.
2//!
3//! ```rust
4//! use nitrite_vector::vector_field;
5//!
6//! // 10 nearest neighbours of the query, higher recall, score cutoff.
7//! let filter = vector_field("embedding")
8//!     .nearest(vec![0.1, 0.2, 0.3], 10)
9//!     .ef(128)
10//!     .min_score(0.75)
11//!     .build();
12//! ```
13
14use nitrite::filter::Filter;
15
16use crate::filter::VectorNearestFilter;
17
18/// Entry point for the vector fluent filter builder.
19pub fn vector_field(field: impl Into<String>) -> VectorFluentFilter {
20    VectorFluentFilter { field: field.into() }
21}
22
23/// Fluent builder anchored to a vector field.
24pub struct VectorFluentFilter {
25    field: String,
26}
27
28impl VectorFluentFilter {
29    /// Begins a k-nearest-neighbor query with the given query vector.
30    pub fn nearest(self, query: Vec<f32>, k: usize) -> VectorNearestBuilder {
31        VectorNearestBuilder {
32            filter: VectorNearestFilter::new(self.field, query, k),
33        }
34    }
35}
36
37/// Builder for a kNN query, allowing optional `ef` / `min_score` refinement.
38pub struct VectorNearestBuilder {
39    filter: VectorNearestFilter,
40}
41
42impl VectorNearestBuilder {
43    /// Sets the query-time `ef` (search width; larger = higher recall, slower).
44    pub fn ef(mut self, ef: usize) -> Self {
45        self.filter = self.filter.with_ef(ef);
46        self
47    }
48
49    /// Sets a minimum similarity score cutoff.
50    pub fn min_score(mut self, min_score: f32) -> Self {
51        self.filter = self.filter.with_min_score(min_score);
52        self
53    }
54
55    /// Finalizes the builder into a [`Filter`].
56    pub fn build(self) -> Filter {
57        Filter::new(self.filter)
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn builds_filter_with_field() {
67        let filter = vector_field("embedding").nearest(vec![1.0, 2.0], 5).build();
68        let s = format!("{filter}");
69        assert!(s.contains("embedding"));
70        assert!(s.contains("nearest"));
71    }
72
73    #[test]
74    fn builder_chains_ef_and_min_score() {
75        let filter = vector_field("emb")
76            .nearest(vec![0.0, 1.0], 3)
77            .ef(64)
78            .min_score(0.5)
79            .build();
80        assert!(format!("{filter}").contains("emb"));
81    }
82}