Expand description
A small DSL for building OData $filter
expressions against Azure AI Search.
See: https://learn.microsoft.com/en-us/azure/search/search-query-odata-filter
This implementation is fully compliant with the OData specification for Azure AI Search. It uses a simplified approach to operator precedence by adding parentheses around logical operations for clarity. This ensures predictable behavior and generates valid OData that Azure AI Search accepts, even if it includes extra parentheses that aren’t strictly necessary.
§Operator Support
This module implements several std::ops
traits to provide ergonomic operator syntax:
!
(Not): Logical negation -!filter
is equivalent tofilter.not()
&
(BitAnd): Logical AND -filter1 & filter2
is equivalent tofilter1.and(filter2)
but with explicit parentheses|
(BitOr): Logical OR -filter1 | filter2
is equivalent tofilter1.or(filter2)
but with explicit parentheses
Note: The operator implementations always add explicit parentheses to avoid any ambiguity about precedence, ensuring the generated OData expressions are unambiguous.
Operator Precedence: Rust’s standard operator precedence applies:
!
(highest precedence)&
|
(lowest precedence)
This means a | b & c
is parsed as a | (b & c)
, not (a | b) & c
.
Use explicit parentheses (a | b) & c
if you need different grouping.
§Examples
use headless_lms_chatbot::search_filter::{SearchFilter, SearchFilterError};
fn example() -> Result<(), SearchFilterError> {
// Simple comparison
let filter = SearchFilter::eq("Rating", 5);
assert_eq!(filter.to_odata()?, "Rating eq 5");
// Using operators for logical combinations (note the explicit parentheses)
let filter = SearchFilter::eq("Category", "Luxury")
| SearchFilter::eq("ParkingIncluded", true)
& SearchFilter::eq("Rating", 5);
assert_eq!(filter.to_odata()?, "(Category eq 'Luxury' or (ParkingIncluded eq true and Rating eq 5))");
// Using negation operator
let filter = !SearchFilter::eq("Deleted", true) & SearchFilter::eq("Status", "active");
assert_eq!(filter.to_odata()?, "((not (Deleted eq true)) and Status eq 'active')");
// Collection operations
let filter = SearchFilter::any_with_filter(
"Rooms",
SearchFilter::raw("room: room/BaseRate lt 200.0")
);
assert_eq!(filter.to_odata()?, "Rooms/any(room: room/BaseRate lt 200.0)");
Ok(())
}
Enums§
- Search
Filter - A composable OData boolean expression.
- Search
Filter Error - Error type for search filter operations.
- Search
Filter Value - A strongly-typed OData filter value.