Search documentation

Search for a page or heading...

tablecn
0

Every built-in operator, the value it takes, and when a rule counts as complete.

An operator is the middle part of a rule: the is in "Status is Paid". Each field type offers its own list (see Fields).

Built-in operators

LabelIdValueOffered on
iseqonetext, number, date, time, boolean, select
is notneonetext, number, select
containscontainsonetext
does not containnotContainsonetext
starts withstartsWithonetext
ends withendsWithonetext
is greater thangtonenumber, date, datetime, time
is greater than or equal togteonenumber, date, datetime, time
is less thanltonenumber, date, datetime, time
is less than or equal tolteonenumber, date, datetime, time
is betweenbetweentwo (from, to)number, date, datetime, time
is any ofina listmultiSelect
is none ofnotIna listmultiSelect
is emptyisEmptynoneevery type except boolean
is not emptyisNotEmptynoneevery type except boolean

The id is what the URL and your code use: status__eq=paid.

On date and datetime fields, the labels read like dates: is on, is after, is on or after, is before, is on or before. On time fields they read like times: is at, is at or after, is at or before. You can change any label with messages.

is between includes both ends. On a date field in the browser, between Sep 1 and Sep 30 means all of September. Your backend may see it differently: 2026-09-30 compared with a timestamp column usually means midnight at the start of that day. mapRule can fix that.

Value shapes

The Value column above is the operator's arity, the shape of the value it needs. The UI uses it to pick the input:

ArityValue in codeExampleIn the URL
nonenullDeleted at is emptydeletedAt__isEmpty
singleone valueStatus is Paidstatus__eq=paid
rangea [from, to] pairAmount is between 10 and 50amount__between=10,50
multia list, at least one itemTags is any of urgent, viptags__in=urgent,vip

When users switch operators, the value is kept if the shape stays the same (is → is not), and cleared otherwise (is → is between).

Complete rules

While users edit, a rule can be half-finished: no operator yet, half a range. On Apply, only complete rules are kept. A rule is complete when:

  1. its field is one of your fields,
  2. its operator is offered for that field,
  3. its value has the right shape, with no empty parts, and each part is valid for the type (a real date, a number…).

The same check runs when a URL is read. That's why a hand-edited or outdated link never crashes anything: rules that don't pass are dropped one by one.

Values are also cleaned up on the way: "42" in a number field becomes 42, "true" in a boolean field becomes true.

You can run the check yourself:

Validate rules
import { isRuleComplete, normalizeRule, normalizeState } from "@querycn/filter-core"

const context = { fields: orderFields }

normalizeRule({ id: "1", field: "amount", operator: "gt", value: "42" }, context)
// → { id: "1", field: "amount", operator: "gt", value: 42 }

normalizeRule({ id: "2", field: "amount", operator: "between", value: ["10", ""] }, context)
// → null (half a range)

isRuleComplete({ id: "3", field: "status", operator: "contains", value: "p" }, context)
// → false (select fields don't offer `contains`)

normalizeState(draft, context) // drops incomplete rules, cleans up the rest

Warnings

Some rules are valid but probably not what the user meant. They're still applied, with a warning icon next to them:

WarningWhen
reversedRangeAn is between whose start is after its end, like 50 – 10. Shown while editing.
conflictThe request sends the same key twice, and most backends only read one. Shown after applying.
unsupportedThe request can't express the rule, so your backend never sees it. Shown after applying.

conflict and unsupported come from the serializer: see Warnings in the UI. In your own UI, useRuleWarnings(rule) returns all three.

Your own operators

Operators are data, so you can add your own, like is not between or a full-text matches. See Add an operator.