Skip to main content
When a server advertises the filter capability, retrieve (and index/delete) accept a small boolean tree over document metadata. Fields and operators are validated against what the server advertised, so a filter is both expressive and safe.

Structure

A filter node is either a combinator (and / or / not, nesting arbitrarily) or a leaf ({ field, op, value }).
node[]
Boolean combinators over child nodes. An empty and/or array is -32602.
node
Negates a single child node.
string
A metadata field name — MUST be one the server advertised in filter.fields, else -32602.
string
A comparison operator (see below). Must be in the advertised filter.operators, else -32005.

Operators

Field types

A server SHOULD advertise filter.fields as a map of field name → type: keyword (exact string), text (tokenised), int, float, bool, date (an RFC 3339 string or epoch-ms), or geo. The allowed operators and the JSON type of value depend on the field type.
A server MUST return -32602 (with error.data.field) when a value’s JSON type is incompatible with the field type, or the field is not advertised. This is also a security boundary: field names are validated precisely because a silently-ignored filter would return wrong — possibly unauthorised — results. Servers MUST parameterise filters into the backing query engine, never string-concatenate. See Security.
Unless a server documents otherwise, string comparison is case-sensitive and byte-ordered.

The canonical builder & validator

Every RCP SDK ships a first-class filter module so you never hand-write the JSON. It has two halves:
  • A builder — typed leaf constructors (eq ne gt gte lt lte in_ nin contains exists) and combinators (all/any/not_, with & | ~ operator sugar) that make a malformed tree impossible to construct.
  • A validatorvalidate(node, fields, operators) that a server runs on the untrusted incoming tree. It returns a normalized tree or a precise -32602 carrying data.field. It enforces field/operator authorization, value-shape (array-vs-scalar), ordered-op-vs-type, combinator/leaf mixing, and a nesting-depth DoS guard.
Don’t roll your own filter parser. A hand-written server parser turns a malformed tree into a generic -32603 crash; the canonical validate() turns it into a clean, actionable -32602 with data.field — and closes the security boundary above for free. The reference Whoosh adapter (examples/whoosh_adapter.py) calls validate() then compiles the trusted tree into engine queries.