Skip to main content
Rule expressions are written in a small expression language with familiar comparison and logical operators. Each expression is a condition. When it evaluates to true on a record, that record is flagged with an alert.
This page is the reference for the full set of operators and patterns. For a walkthrough of writing your first rule, see Create a Data Rule.

Variables

Variables reference the data Mangrove evaluates the expression against. They are wrapped in double curly braces and always carry a prefix naming what kind of thing they point at.
Use double quotes around a node name that contains spaces or other special characters, as in the third example. The prefix has to match what the rule runs on. A Data Points rule cannot reference {{node.*}}, and a Batch Calculation rule cannot reference {{data-point.*}}. Mismatches are rejected when you save. What the editor offers follows from that:
  • Data Points rules use data point slugs. These rules apply across the whole project, so autocomplete offers every non-static data point type in it, and the rule evaluates against any event whose data points satisfy the condition. One rule reads a single event type: a condition referencing types from two of them is rejected when you save, and autocomplete does not narrow the list to stop you writing one.
  • Batch Calculation rules use nodes in the selected model.
Type {{ in the rule editor to open autocomplete. Each suggestion shows the variable name and its description, value type, or unit when available, and inserts the full prefixed form for you.

Comparison operators

Logical operators

Combine conditions with AND, OR, and NOT. Use parentheses to group. NOT binds tightest, then AND, then OR.

Range and set operators

Text operators

String literals use single quotes. MATCHES patterns use Ruby regular expression syntax, and each match attempt is bounded by a one-second timeout, so keep patterns anchored and avoid ones that backtrack heavily. There is no NOT MATCHES operator, and the same goes for the other text operators. Negate them with the NOT prefix instead: NOT {{data-point.lot_code}} matches '[A-Z]{2}-[0-9]+'.

Presence operators

Use these to check whether a value was recorded.
Two cases fall between the two operators, and neither one catches them. A text data point holding an empty string is not missing, because a value was stored, and it is not present either. A boolean holding false behaves the same way. Test for those with = '' and = false instead. A reading that was never submitted has no data point for the rule to evaluate, so IS MISSING stays out of its reach.

Aggregates

Aggregate functions roll a set of values into a single number. Use one as the left side of a comparison.
SUM, AVG, MIN and MAX need a numeric data point type and are rejected when you save otherwise. COUNT works on any type. By default an aggregate covers only the data points on the event being evaluated. To ask a question that spans events, add a window.

Windowed aggregates

Add a WITHIN clause inside the aggregate’s parentheses to widen the set from one event to many. Use it for rules about how often something happens, or about a total across a period.
Pick the mode that matches the question you are asking.

ROLLING

A sliding window centred on the data point being evaluated, reaching the full duration in both directions. For a value captured at a single point in time, ROLLING 7.days therefore spans 14 days: the seven days before it and the seven after. Where the event carries a start and an end, the window reaches out from both, so the span is the event’s own duration plus the window twice. Use it for proximity and anomaly questions, such as flagging a cluster of readings around one point in time.
Durations take two forms: A ROLLING duration has to be greater than zero. ROLLING 0.days is rejected when you save.

CALENDAR

The calendar bucket the evaluated data point falls in, in your account’s timezone. Use it for cohort and reporting-period questions, such as “no more than one of these per calendar month”.
Units are SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, and YEAR. Weeks start on Monday. The sub-hour units suit duplicate detection at a known cadence, such as one meter reading per clock minute. Calendar buckets are absolute. February 27 and March 2 sit in different MONTH buckets and never pair, however close together they are. Two readings two seconds apart at 12:00:59 and 12:01:01 fall in different MINUTE buckets for the same reason. Use ROLLING when you care about elapsed time, and CALENDAR when you care about the clock bucket.

What to know before you use one

  • The evaluated data point is in the set when the window names its own type. COUNT(...) = 1 is therefore true for a data point with no neighbours, so write COUNT(...) > 1 to mean “more than just this one”. In a rule that references several types, a value is not a member of a window over a different type.
  • The preview cannot evaluate a windowed aggregate. It reads them against an empty set, so COUNT previews as 0 and the others as no value. Preview the rest of the condition there, and expect the window itself to be exercised only once the rule is saved.
  • Windows only work on {{data-point.*}} variables. A WITHIN clause on a {{node.*}} reference is rejected when you save, so Batch Calculation rules cannot use one.
  • The rule’s effective dates clamp the window. A CALENDAR MONTH bucket is cut short if the rule only became effective partway through that month.
  • You can use more than one windowed aggregate in a rule. Each resolves its own set independently.

Booleans and numbers

  • Booleans are written true and false (case-insensitive).
  • Numbers are written without quotes. Both integers and decimals work: 0, 42, 3.14, 0.005. Negative numbers are allowed.

Common patterns

These examples assume your project has data points with the slugs shown. Substitute slugs that exist in your project.

Tips for writing good rules

  • Phrase the rule as the failure case. A rule with the expression {{data-point.ph}} not between 6.0 and 8.0 triggers when pH is out of range, which is the alert you want.
  • Validate before saving. Validating previews the matches from the last 90 days. Use it to catch over-eager rules before they generate noise. When nothing matches, a range filter appears with the result so you can look further back.
  • Cover every shape of an empty value. IS MISSING catches a data point with no value stored. It misses a text data point holding an empty string and a boolean holding false, so a rule that has to catch those needs each test spelled out with its own variable: {{data-point.lab_sample_id}} IS MISSING OR {{data-point.lab_sample_id}} = ''.
  • Say why in the rule name. Expressions are terse and a rule carries no separate description field, so the name and the alert message are where you explain what the rule is for.