Skip to main content

StrategySelector

Struct StrategySelector 

Source
pub struct StrategySelector { /* private fields */ }
Expand description

Picks a concrete FilterStrategy for a validated filter from its estimated selectivity — the Tier-2, tunable counterpart to choose_strategy.

The rule is simple and monotone: a narrow predicate (low estimate_selectivity, at or below the threshold) resolves to FilterStrategy::PreFilter, because evaluating it up front skips the distance computation for the rows it rejects; a broad predicate resolves to FilterStrategy::PostFilter, because pre-filtering would materialise nearly the whole corpus for little gain. The selector never returns FilterStrategy::Auto (it is the thing that resolves it) or FilterStrategy::InFilter (which needs graph-traversal co-design).

The type is immutable: with_prefilter_threshold returns a new selector rather than mutating in place.

§Examples

use iqdb_filter::{FilterEvaluator, FilterStrategy, StrategySelector};
use iqdb_types::{Filter, Value};

let selector = StrategySelector::new().with_prefilter_threshold(0.3);

let narrow = FilterEvaluator::new(Filter::eq("id", Value::Int(7)))?;
let broad = FilterEvaluator::new(Filter::neq("id", Value::Int(7)))?;

assert_eq!(selector.choose(&narrow), FilterStrategy::PreFilter);
assert_eq!(selector.choose(&broad), FilterStrategy::PostFilter);

Implementations§

Source§

impl StrategySelector

Source

pub fn new() -> Self

Creates a selector with the DEFAULT_PREFILTER_THRESHOLD.

§Examples
use iqdb_filter::{StrategySelector, DEFAULT_PREFILTER_THRESHOLD};

let selector = StrategySelector::new();
assert_eq!(selector.prefilter_threshold(), DEFAULT_PREFILTER_THRESHOLD);
Source

pub fn with_prefilter_threshold(self, threshold: f64) -> Self

Returns a new selector that pre-filters when estimated selectivity is at or below threshold.

threshold is clamped to [0.0, 1.0]: 0.0 pre-filters only the most extreme predicates (effectively always post-filter), 1.0 always pre-filters.

§Examples
use iqdb_filter::StrategySelector;

let always_pre = StrategySelector::new().with_prefilter_threshold(1.0);
assert_eq!(always_pre.prefilter_threshold(), 1.0);

// Out-of-range values are clamped, never panic.
let clamped = StrategySelector::new().with_prefilter_threshold(2.5);
assert_eq!(clamped.prefilter_threshold(), 1.0);
Source

pub fn prefilter_threshold(&self) -> f64

The selectivity cutoff this selector uses.

Source

pub fn choose(&self, evaluator: &FilterEvaluator) -> FilterStrategy

Resolves the strategy for evaluator’s filter.

Returns FilterStrategy::PreFilter when the estimated selectivity is at or below prefilter_threshold, and FilterStrategy::PostFilter otherwise.

§Examples
use iqdb_filter::{FilterEvaluator, FilterStrategy, StrategySelector};
use iqdb_types::{Filter, Value};

let evaluator = FilterEvaluator::new(Filter::eq("k", Value::Int(1)))?;
assert_eq!(StrategySelector::new().choose(&evaluator), FilterStrategy::PreFilter);
Source

pub fn choose_with_index<K>( &self, evaluator: &FilterEvaluator, index: &MetadataIndex<K>, ) -> FilterStrategy
where K: Clone + Eq + Hash,

Resolves the strategy using the index-backed selectivity estimate from index (MetadataIndex::estimate_selectivity), which uses real posting counts where it can.

Prefer this over choose when an index is available: the count-based estimate is sharper than the structural one, so the pre/post decision is better informed.

§Examples
use iqdb_filter::{FilterEvaluator, FilterStrategy, MetadataIndex, StrategySelector};
use iqdb_types::{Filter, Metadata, Value};

// 1 of 4 rows matches: a genuinely narrow predicate the index can see.
let rows = [
    (0_usize, [("tier".to_string(), Value::Int(1))].into_iter().collect::<Metadata>()),
    (1, [("tier".to_string(), Value::Int(2))].into_iter().collect::<Metadata>()),
    (2, [("tier".to_string(), Value::Int(2))].into_iter().collect::<Metadata>()),
    (3, [("tier".to_string(), Value::Int(2))].into_iter().collect::<Metadata>()),
];
let index = MetadataIndex::build(&["tier"], rows.iter().map(|(k, m)| (*k, Some(m))));

let evaluator = FilterEvaluator::new(Filter::eq("tier", Value::Int(1)))?;
let selector = StrategySelector::new();
assert_eq!(selector.choose_with_index(&evaluator, &index), FilterStrategy::PreFilter);

Trait Implementations§

Source§

impl Clone for StrategySelector

Source§

fn clone(&self) -> StrategySelector

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for StrategySelector

Source§

impl Debug for StrategySelector

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for StrategySelector

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<E> WithErrorCode<E> for E

Source§

fn with_code(self, code: impl Into<String>) -> CodedError<E>

Attach an error code to an error