Skip to main content

Query syntax

This guide explains the full syntax users can type into FilterQuery. It covers everything from matching a single field value to building multi-condition queries with logical operators and grouping.

How the syntax works

Every query is a sequence of conditions. Each condition targets a field by name, followed by a colon and one or more values:

status: Open

Multiple conditions separated by spaces default to AND:

status: Open assignee: john.doe priority: High

The parser converts typed input into the rule. This structure is a tree of rules connected with glue: "and" or glue: "or". Simple queries produce a single flat filtering rule, while complex queries produce nested filtering rule groups.

Field names can be either the field's id or its sanitized label. Labels appear in the input, while the value prop stores the corresponding IDs. For example, a field { id: "first_name", label: "First Name" } is typed as FirstName: and stored as first_name:.

Values containing spaces, reserved words, or special characters must be quoted:

type: "Bug Report"
status: "In Progress"

Single (') and double (") quotes both work. Use \ to escape a quote inside a string, or switch to the opposite quote type to avoid escaping.

Basic field-value pairs

Match a field to an exact value with field: value:

status: Open
assignee: jane.doe
country: Germany

Each condition produces a rule with filter: "equal":

{ "field": "status", "filter": "equal", "value": "Open" }

Multiple values and exclusions

Multiple values (OR within a field)

Comma-separate values to match any of them:

status: Open, "In Progress", Review
priority: High, Critical

This produces a single rule with includes:

{ "field": "status", "includes": ["Open", "In Progress", "Review"] }

Excluding values

Prefix a value with - to exclude it:

status: -Closed
priority: -Low, -Normal
type: -"Won't Fix"

A single exclusion produces filter: "notEqual". Multiple exclusions expand into an AND group:

{
"glue": "and",
"rules": [
{ "field": "status", "filter": "notEqual", "value": "Closed" },
{ "field": "status", "filter": "notEqual", "value": "On Hold" }
]
}

- before the field name (-status: Open) isn't valid. Negation belongs on the value side.

Text matching operators

Wildcards

Use * as a wildcard for partial text matching:

PatternMeaningExample
valueExact matchname: Alex
value*Starts withname: Alex*
*valueEnds withemail: *@gmail.com
*value*Containstitle: *urgent*
name: Alex*
email: *@company.com
title: *crash*

Word operators

contains, starts, and ends are word-based alternatives to wildcards:

OperatorMeaningExample
containsContains substringname: contains Alex
startsStarts withname: starts Alex
endsEnds withname: ends Smith
-containsDoes not containname: -contains spam
-startsDoes not start withname: -starts test_
-endsDoes not end withemail: -ends @temp.com
description: contains "critical error"
email: -ends "@temp.com"
title: -contains deprecated

name: Alex* and name: starts Alex produce the same output: { filter: "beginsWith", value: "Alex" }.

To search for the literal word contains, starts, or ends as a field value, quote it:

keyword: "contains"

Numeric and date comparisons

Use comparison operators on number and date fields:

OperatorMeaningExample
:Equalsage: 25
>Greater thanage: >25
>=Greater or equalvotes: >=100
<Less thanprice: <50
<=Less or equalcreated: <=2024-01-01

Use .. for a bounded range (inclusive on both ends):

age: 25 .. 50
created: 2024-01-01 .. 2024-12-31
price: 100 .. 500

A range produces filter: "between" with a { start, end } value object:

{ "field": "age", "filter": "between", "value": { "start": 25, "end": 50 } }

Negative numbers require special handling. -30 is parsed as "not equal to 30", not "equal to negative 30". To match a literal negative number, quote it: temperature: "-10". Comparison operators don't have this issue: temperature: >-10 works as expected.

Date predicates

Date fields support filtering by year or month without a full date value.

Auto-inferred predicates

The parser infers precision from the value format:

InputInterpreted asMatches
start: 2024start.year: 2024All dates in 2024
start: 2024-06year-month filterAll dates in June 2024
start: 2024-06-15exact dateJune 15, 2024 only
start: 2024
start: 2024-06
start: >=2024-06
start: 2024-01 .. 2024-06

Explicit predicates

Use field.predicate: syntax to filter by year or month directly:

PredicateMeaningExample
yearMatch by year onlystart.year: 2024
monthMatch by month (1–12)start.month: 6
start.year: 2024
start.year: >2020
start.month: 6
start.month: 1, 2, 3

start: 2024 and start.year: 2024 produce the same output:

{ "field": "start", "predicate": "year", "filter": "equal", "value": 2024 }

All comparison operators and ranges work with predicates: start.year: 2020 .. 2024.

For fields whose labels include a dot after sanitization, the predicate attaches to the sanitized label. A field { id: "start", label: "Start Date" } sanitizes to StartDate, so the predicate syntax is StartDate.year: 2024.

Tags and free text

Tags

Prefix a value with # to match it across all fields without specifying one. Tags do exact matching:

#Urgent
#"In Progress"
-#Closed

Combine multiple tags with commas:

#bug, #feature
#Open, -Closed

A tag produces a rule with field: "*":

{ "field": "*", "filter": "equal", "value": "Urgent" }

To enable autocomplete suggestions for tags, add a "#" key to the options hash.

Free text

With parse="allowFreeText" (the default), plain words without a field name run a contains search across all fields. Each word becomes a separate rule, combined with AND:

Alex Smith
urgent bug

Prefix a word with - to exclude it:

-spam
Alex -test

Alex Smith produces:

{
"glue": "and",
"rules": [
{ "field": "*", "filter": "contains", "value": "Alex" },
{ "field": "*", "filter": "contains", "value": "Smith" }
]
}

With parse="strict", unrecognized text triggers a validation error instead.

Logical operators and grouping

AND and OR

Use and and or to combine conditions explicitly:

project: Alpha and status: Open
status: Open or status: "In Progress"
type: Bug and status: -Closed and assignee: jane.doe

Conditions without an explicit operator default to AND.

Grouping with parentheses

Use () to control evaluation order:

project: Alpha and (status: Open or status: "In Progress")
priority: High or (votes: >=100 and status: Open)

Parentheses produce nested filtering rule groups:

{
"glue": "and",
"rules": [
{ "field": "project", "filter": "equal", "value": "Alpha" },
{
"glue": "or",
"rules": [
{ "field": "status", "filter": "equal", "value": "Open" },
{ "field": "status", "filter": "equal", "value": "In Progress" }
]
}
]
}

and, or, contains, starts, and ends are reserved words. To use any of them as a literal field value, quote it: operator: "and".

FilterQuery: query string