README

#core/filter

Filter expression DSL for attribute-based filtering.

#Expression Types

#Leaf Expressions

  • Match(key, value): Exact match (key == value)
  • Range(key, range): Numeric range query
  • Exists(key): Key exists and is not null
  • IsNull(key): Key is null or doesn't exist

#Composite Expressions

  • Must([exprs]): All must match (AND)
  • MustNot([exprs]): None must match (AND NOT)
  • Should([exprs], min): At least N must match (OR with minimum)

#Filter Strategies

  • PreFilter: Filter before vector search (faster for selective filters)
  • PostFilter: Filter after vector search (simpler, always correct)
  • Auto: Automatically choose based on selectivity

#Usage

let filter = FilterExpr::must([
FilterExpr::match_("category", @types.String("electronics")),
FilterExpr::range("price", NumericRange::between(10.0, 100.0)),
])
let matches = filter.evaluate(attrs)

#
FilterExpr

pub(all) enum FilterExpr {
Leaf(LeafExpr)
Must(Array[FilterExpr])
MustNot(Array[FilterExpr])
Should(Array[FilterExpr], Int)
}

Filter expression (can be nested)
impl Show for FilterExpr

#
FilterExpr::exists

fn FilterExpr::exists(key : String) -> FilterExpr

Create an Exists filter

#
FilterExpr::is_null

fn FilterExpr::is_null(key : String) -> FilterExpr

Create an IsNull filter

#
FilterExpr::match_

Create a Match filter

#
FilterExpr::must

fn FilterExpr::must(exprs : Array[FilterExpr]) -> FilterExpr

Create a Must (AND) filter

#
FilterExpr::must_not

fn FilterExpr::must_not(exprs : Array[FilterExpr]) -> FilterExpr

Create a MustNot (NOT) filter

#
FilterExpr::range

Create a Range filter

#
FilterExpr::should

fn FilterExpr::should(exprs : Array[FilterExpr], min? : Int) -> FilterExpr

Create a Should (OR) filter with minimum matches

#
FilterStrategy

pub(all) enum FilterStrategy {
PreFilter
PostFilter
Auto
}

Filter strategy for search

#
LeafExpr

pub(all) enum LeafExpr {
Match(String,
AttrValue
)
Range(String,
NumericRange
)
Exists(String)
IsNull(String)
}

Leaf expression types
impl Show for LeafExpr

#
compile_filter

Compile a filter expression to a predicate function

#
eval_filter

fn eval_filter(expr : FilterExpr, attrs :
Attrs
) -> Bool

Evaluate a filter expression against attrs

#
filter_to_json

fn filter_to_json(expr : FilterExpr) -> String

Serialize a FilterExpr to JSON string.

#
get_candidates_basic

Get candidate IDs from a basic attribute index using a filter expression Returns None if pre-filtering is not possible (should use post-filter)

#
parse_filter_json

fn parse_filter_json(json : String) -> FilterExpr?

Parse a JSON string into a FilterExpr. Returns None for empty/invalid input.

#
resolve_candidates_bptree

Resolve candidate IDs from a B+ tree attribute index. Every FilterExpr variant is resolved through the index — there is no fallback to post-filtering. This guarantees a single execution path regardless of the expression shape.

  • IsNull(key): complement of exists(key) against all indexed IDs
  • MustNot(exprs): complement of union(resolve(e)) against all IDs
  • Should(exprs, min>1): count per-ID and threshold