Expression Builder
This guide introduces expr::ExprBuilder, then shows how to reuse typed expressions in filters ($expr), projections, and updates.
Building Typed Expressions
ExprBuilder creates BSON expression trees with compile-time constraints.
use tnuctipun::{expr, FieldWitnesses, MongoComparable};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, FieldWitnesses, MongoComparable)]
struct Product {
pub price: f64,
pub stock: i32,
pub reserved: i32,
pub min_stock: i32,
}
fn expression_basics() {
let b = expr::empty::<Product>();
let stock = b.select::<product_fields::Stock>();
let reserved = b.select::<product_fields::Reserved>();
// available = stock - reserved
let available = b.subtract(stock, reserved);
// low_stock = available < min_stock
let low_stock = b.lt(available, b.select::<product_fields::MinStock>());
assert_eq!(
low_stock.into_bson(),
bson::doc! {
"$lt": [
{ "$subtract": ["$stock", "$reserved"] },
"$min_stock"
]
}
.into()
);
}
See also: Finding Documents - Expression Builder ($expr)
Using Expressions in Filters ($expr)
FilterBuilder::expr inserts a typed boolean expression under MongoDB’s $expr operator.
use tnuctipun::{expr, filters, FieldWitnesses, MongoComparable};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, FieldWitnesses, MongoComparable)]
struct Product {
pub name: String,
pub stock: i32,
pub reserved: i32,
pub min_stock: i32,
}
fn filter_with_expr() {
let b = expr::empty::<Product>();
let low_stock = b.lt(
b.subtract(
b.select::<product_fields::Stock>(),
b.select::<product_fields::Reserved>(),
),
b.select::<product_fields::MinStock>(),
);
let filter_doc = filters::empty::<Product>()
.eq::<product_fields::Name, _>("Widget".to_string())
.expr(low_stock)
.and();
// Produces a query containing "$expr": { ... }
println!("{}", filter_doc);
}
See also: Finding Documents
Using Expressions in Projections
projection::ProjectionBuilder::project_expr lets you compute projected field values using typed expressions.
use tnuctipun::{expr, projection, FieldWitnesses, MongoComparable};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, FieldWitnesses, MongoComparable)]
struct InventoryView {
pub stock: i32,
pub reserved: i32,
pub available: i32,
}
fn projection_with_expr() {
let b = expr::empty::<InventoryView>();
let mut proj = projection::empty::<InventoryView>();
proj.project_expr::<inventoryview_fields::Available, _>(
b.subtract(
b.select::<inventoryview_fields::Stock>(),
b.select::<inventoryview_fields::Reserved>(),
),
);
let projection_doc = proj.build();
println!("{}", projection_doc);
}
See also: Finding Documents - Projections
Using Expressions in Updates
updates::UpdateBuilder::set_expr applies an expression as the new value of a field.
use tnuctipun::{expr, updates, FieldWitnesses, MongoComparable};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, FieldWitnesses, MongoComparable)]
struct ScoreCard {
pub score: i32,
pub bonus: i32,
}
fn update_with_expr() {
let b = expr::empty::<ScoreCard>();
let update_doc = updates::empty::<ScoreCard>()
.set_expr::<scorecard_fields::Score, _>(
b.add(
b.select::<scorecard_fields::Score>(),
vec![b.select::<scorecard_fields::Bonus>()],
),
)
.build();
println!("{}", update_doc);
}
See also: Updating Documents - Expression-Based Updates
Notes on Type Constraints
- Equality comparisons (
eq,ne) useMongoComparablebounds. - Ordering comparisons (
gt,gte,lt,lte) requireMongoOrderedevidence. - If an expression uses an unsupported ordering type pair, compilation fails early.
See also: Derive Macros - MongoComparable Macro