Multi-Valued Field Evaluation¶
The evaluation engine handles fields that contain lists or nested lists of values.
- Comparison operators (
==,>,<, etc.) use "any" semantics:Trueif any value in the list meets the criteria. - Inequality (
!=) uses "none" semantics:Trueif no value in the list meets the criteria.
Examples¶
from therismos import F, unwind_data
tags = F("tags")
scores = F("scores", int)
# Equality: True if "python" is ANY of the tags
expr_eq = tags == "python"
assert expr_eq.evaluate(unwind_data({"tags": ["java", "python", "rust"]})) is True
# Inequality: True if "python" is NONE of the tags
expr_ne = tags != "python"
assert expr_ne.evaluate(unwind_data({"tags": ["java", "rust"]})) is True
assert expr_ne.evaluate(unwind_data({"tags": ["java", "python"]})) is False
# Greater Than: True if ANY score is > 80
expr_gt = scores > 80
assert expr_gt.evaluate(unwind_data({"scores": [60, 75, 90]})) is True
# Nested lists are flattened automatically
assert expr_gt.evaluate(unwind_data({"scores": [[60, 75], [90, 40]]})) is True
Membership and Regex on Multi-Valued Fields¶
is_in and matches return True if any value in the field's list satisfies the condition:
import re
status = F("status")
expr = status.is_in("active", "pending", "approved")
result = expr.evaluate(unwind_data({"status": "active"})) # True
log_messages = F("logs")
expr = log_messages.matches(r"ERROR:", re.IGNORECASE)
data = {"logs": ["INFO: User logged in", "ERROR: Connection failed"]}
result = expr.evaluate(unwind_data(data)) # True — one message matches
phone = F("phone")
expr = phone.is_null()
result = expr.evaluate(unwind_data({"phone": None})) # True