Vibha's data and monitoring platform · vibha.org

Operators reference

Think of this page like the button reference at the back of a calculator's manual — you do not read it start to finish, you look up the button you need. It is the complete, closed set of operators the rules engine understands, the same list the rule editor's operator picker offers, grouped the same way. There is no way to add a new one at runtime; every operator here always produces a value or a blank and never crashes, so a typo in a formula can never turn into an error page in front of a respondent.

Comparison

These answer a simple yes-or-no question, like comparing two numbers on a scale — is one bigger, smaller, or the same as the other? They work on numbers andon dates the same way, so “which date comes later” uses the exact same operator as “which number is bigger” — no separate set of date operators to remember.

OperatorInputsWhat it checks
eq(a, b)2a equals b. Works on text, numbers, booleans, and multi-choice lists (order-insensitive).
neq(a, b)2a does not equal b.
gt(a, b)2a is greater than b. Works on numbers and date strings.
gte(a, b)2a is greater than or equal to b.
lt(a, b)2a is less than b.
lte(a, b)2a is less than or equal to b.
between(value, low, high)3value ≥ low and value ≤ high (inclusive on both ends). Works on numbers and dates.

Logic

These combine several yes-or-no answers the way you would in a sentence like “if it is raining andI don't have an umbrella, take a taxi” — each piece is itself true or false, and these operators combine them into one final answer.

OperatorInputsWhat it does
and(a, b, …)1 or moreTrue when every input is true. Takes any number of inputs.
or(a, b, …)1 or moreTrue when at least one input is true.
not(a)1Inverts the truth value of its input.
if(condition, then, otherwise)3Returns the "then" value when condition is true, the "otherwise" value when false. Useful in Calculate rules.
coalesce(a, b, …)1 or moreReturns the first input that is not blank. Use to fall back to a default value.

Presence

These only ask “did anyone answer this question at all?” — completely separate from what they answered. A question left blank and a question answered with 0or “no” are very different things, and these operators are how a rule tells them apart.

OperatorInputsWhat it checks
isFilled(field)1True when the question has any answer — including the number 0 or the text "false".
isBlank(field)1True when the question has no answer — it was skipped or not yet reached.

Maths

The same operations as a pocket calculator — add, subtract, multiply, round — just applied to a form's own answers instead of numbers you type in by hand. All of them return blank when an input cannot be treated as a number, and division or remainder by zero returns blank rather than an error or a nonsense result.

OperatorInputsWhat it computes
add(a, b, …)2 or moreSum of all inputs.
sub(a, b)2a minus b.
mul(a, b, …)2 or moreProduct of all inputs.
div(a, b)2a divided by b. Returns blank when b is zero.
mod(a, b)2Remainder of a ÷ b. Returns blank when b is zero.
abs(a)1Absolute (positive) value of a.
floor(a)1Round down to the nearest whole number.
ceil(a)1Round up to the nearest whole number.
round(a) or round(a, digits)1–2Round to the nearest whole number, or to the specified number of decimal places (0–12).
min(a, b, …)1 or moreSmallest of all inputs.
max(a, b, …)1 or moreLargest of all inputs.

Dates

These answer questions like “how many years, months or days between these two dates” — the same counting you would do on a calendar by hand, done automatically and without an off-by-one mistake. Date operators accept YYYY-MM-DDstrings (what date fields store) and full ISO datetime strings. All arithmetic runs in UTC so the server's recomputation agrees with the browser regardless of the respondent's timezone.

OperatorInputsWhat it returns
today()0Today's date as YYYY-MM-DD. On the server, the submission timestamp is used — not the browser clock.
yearsBetween(from, to)2Whole years elapsed from → to (how many birthdays have passed). Pair with today() to compute age.
monthsBetween(from, to)2Whole calendar months elapsed from → to.
daysBetween(from, to)2Full days elapsed from → to.
addDays(date, n)2A date n days after date. n may be negative.
addMonths(date, n)2A date n months after date. End-of-month clamped: 31 Jan + 1 month = 28 Feb, never 3 Mar.
formatDate(date, pattern)2Format a date for display. Supported tokens: YYYY MM DD HH mm. Example: formatDate(dob, "DD/MM/YYYY")

Text

Basic text manipulation — joining words together, changing case, checking whether one bit of text sits inside another — the same everyday things a phone's find-and-replace or autocomplete already does for you.

OperatorInputsWhat it returns
concat(a, b, …)1 or moreJoins all inputs as text. Blank values contribute nothing — not the word "null".
upper(a)1Converts text to UPPERCASE.
lower(a)1Converts text to lowercase.
trim(a)1Removes leading and trailing spaces.
length(a)1Number of characters in text, or number of selected options in a multi-choice answer.
contains(a, b)2Case-insensitive: does text a contain text b? Also works on multi-choice lists: does the selection include option b?
startsWith(a, b)2Case-insensitive: does text a start with text b?

Lists

For questions where someone can tick more than one box, or fill in the same section several times over — every household member, every issue found on a visit — these operators count, add up, or check across all of those entries at once, the way you might tally a show of hands instead of asking one person at a time.

OperatorInputsWhat it returns
count(list)1Number of items in the list. For a multi-choice question: how many options are selected.
includes(list, value)2True when the list contains the given value.
sumOf(list)1Adds every numeric item in the list. Useful on repeating sections where each entry has a number field.
anyOf(list)1True when at least one item in the list is truthy.
allOf(list)1True when every item in the list is truthy. True for an empty list (vacuously).

Lookup: auto-fill from a dropdown list

When your dropdown list carries extra data in its metadata columns — a UDISE code on a school list, a district code on a village list — a Calculate rule can copy that data into a read-only field the instant the respondent picks an option. No second dropdown, no transcription error.

OperatorInputsWhat it returns
lookup(list, field, column)3The value stored in column of whichever item from list the respondent picked in field. Returns blank if the question is unanswered, the item is not in the list, or that column has no value for the item.

Cross-form references

Like a form remembering something you already told a different form, so nobody has to type the same answer twice. A form linked to a record type can read an answer given on another form for the same record. A follow-up visit form can pre-fill the district from the registration form; a score form can read the previous baseline.

When valueWhich submission is read
LatestThe most recent submission of that form for this record.
FirstThe earliest submission of that form for this record.
RegistrationThe submission that created the record.

Calculated values are recomputed on the server

Limits enforced at publish time

These limits exist so a rule set can never get so tangled that nobody — not the person who wrote it, not the system evaluating it — can work out what it actually does. The compiler checks the complete rule set when you publish, and rules that would fail at runtime are rejected before any respondent ever sees the form.

LimitValueWhy
Rules per form200Keeps the compiled plan manageable and prevents accidental runaway automation.
Nodes per expression256Prevents trees so deeply nested they are unreadable to authors and slow to evaluate.
Expression depth24 levelsA limit on nesting, not total node count.

The following are also caught and reported at publish time:

  • Unknown operators — an operator name not in the built-in set is rejected. There is no way to inject custom code or eval.
  • Unknown field keys — a reference to a question that does not exist (or was deleted after the rule was written) is caught with the offending rule named.
  • Dependency cycles— if field A's Calculate rule references B and B's rule references A, publication fails and both fields are named. Detection runs across the whole rule set, not rule by rule.
  • Lookup restriction — the second argument to lookup() must be a bare field reference. An expression there would require multi-pass evaluation, which the engine does not support.