Comparison operators
| Operator | Example | Description |
|---|
= | level = "error" | Exact match (case-insensitive for strings) |
!= | level != "debug" | Not equal |
> | status > 499 | Greater than |
< | latency_ms < 100 | Less than |
>= | status >= 500 | Greater than or equal |
<= | latency_ms <= 200 | Less than or equal |
CONTAINS | message CONTAINS "timeout" | Case-insensitive substring search |
MATCHES | message MATCHES "timeout" | Case-insensitive substring match (same behavior as CONTAINS) |
Numeric comparisons work on integer and float fields. String comparisons are always case-insensitive.
MATCHES is currently implemented as a case-insensitive substring search, identical to CONTAINS. Regex support is planned for a future release.
# Exact string match (case-insensitive)
zeal 'FROM app.json WHERE level = "error"'
# Not equal
zeal 'FROM app.json WHERE level != "debug"'
# Numeric range
zeal 'FROM app.json WHERE status >= 500'
zeal 'FROM app.json WHERE latency_ms < 100'
# Substring search (case-insensitive)
zeal 'FROM app.json WHERE message CONTAINS "timeout"'
# Substring match (same behavior as CONTAINS)
zeal 'FROM app.json WHERE message MATCHES "timeout"'
Boolean logic
Use AND, OR, and NOT to combine expressions.
AND
Both sides must match:
zeal 'FROM app.json WHERE level = "error" AND status >= 500'
Either side must match:
zeal 'FROM app.json WHERE level = "error" OR level = "fatal"'
NOT
Inverts a condition:
zeal 'FROM app.json WHERE NOT level = "debug"'
Parenthesized expressions
Use parentheses to control precedence. AND binds more tightly than OR, so parentheses are required when mixing the two:
# Without parentheses, AND is evaluated first:
# level = "error" AND (status >= 500 OR service = "auth")
zeal 'FROM app.json WHERE level = "error" AND status >= 500 OR service = "auth"'
# Parentheses make the intent explicit:
zeal 'FROM app.json WHERE (level = "error" OR level = "fatal") AND status >= 500'
Operator precedence
From highest to lowest:
NOT
AND
OR
WITHIN...OF (temporal — see Temporal correlation)
When in doubt, use parentheses.
Level values
When filtering on level, Zeal normalizes these aliases automatically:
| Canonical level | Recognized values |
|---|
trace | trace |
debug | debug, dbg |
info | info, information |
warn | warn, warning |
error | error, err |
fatal | fatal, critical, crit, panic, emerg |
All comparisons are case-insensitive, so level = "ERROR" and level = "error" produce identical results.