Skip to content

Filtering

The filter DSL is a JSON-based query language for finding thogits. Filters compose with logical operators and support everything from full-text search to cross-reference traversal.

All filter examples work with both the REST API (POST /api/thogits/search) and Views (saved filter presets).

Searches across both name and description fields (case-insensitive):

{ "search": "quarterly review" }

String filter applied to the thogit’s name:

{ "name": { "contains": "bug" } }

String filter applied to the thogit’s description:

{ "description": { "starts_with": "TODO" } }

Check whether a thogit has a specific tag applied. Accepts tag name or tag ID:

{ "has_tag": "Task" }
{ "has_tag": "01JQA4N8E3KXYZ..." }

Use dot notation to filter by a tag’s field value. The left side is TagName.fieldName, the right side is an operator:

{ "Task.priority": ["High"] }
{ "Task.due_date": { "lt": "2025-06-01" } }

Combine filters with and, or, and not:

{
"and": [
{ "has_tag": "Task" },
{ "Task.status": { "match": "Todo" } },
{ "not": { "Task.priority": { "match": "Low" } } }
]
}

and and or require at least 2 conditions. not wraps a single filter.

Operators determine how a field value is compared. The right-hand side of a dot-notation filter is always an operator expression.

Bare values are shorthand for equality:

{ "Task.assignee": "01JQX..." }

is equivalent to {"eq": "01JQX..."}.

Bare ValueEquivalent To
"text"{"eq": "text"}
42{"eq": 42}
trueBoolean equality
null{"is_null": true}
OperatorDescription
{"eq": "x"}Exact match
{"neq": "x"}Not equal
{"contains": "x"}Substring match
{"starts_with": "x"}Prefix match
{"matches": "^reg.*ex$"}Regex match
OperatorDescription
{"eq": 5}Equal
{"neq": 5}Not equal
{"gt": 5}Greater than
{"gte": 5}Greater than or equal
{"lt": 5}Less than
{"lte": 5}Less than or equal

Date operators use the same keys as number operators but with date strings:

OperatorDescription
{"eq": "2025-04-15"}Exact date match
{"gt": "2025-01-01"}After a date
{"lte": "2025-12-31T23:59:59"}On or before a datetime

Both YYYY-MM-DD and YYYY-MM-DDTHH:MM:SS formats are supported.

OperatorDescription
{"exists": true}Field has a non-null value
{"exists": false}Field is null or missing
{"is_null": true}Field is null
{ "Task.priority": { "in": ["High", "Critical"] } }

Matches if the field value is any of the listed values. Works with Select and MultiSelect fields too.

OperatorDescription
{"match": "Done"}Variant name equals (Select) or is contained (MultiSelect)
{"select_gt": "InProgress"}Variant position is after the given variant
{"select_gte": "InProgress"}Variant position is at or after
{"select_lt": "Done"}Variant position is before
{"select_lte": "Done"}Variant position is at or before
{ "has_tag": "Task" }
{
"and": [
{ "has_tag": "Task" },
{ "not": { "Task.status": { "match": "Done" } } }
]
}

3. Find high-priority tasks due this month

Section titled “3. Find high-priority tasks due this month”
{
"and": [
{ "has_tag": "Task" },
{ "Task.priority": { "in": ["High", "Critical"] } },
{ "Task.due_date": { "gte": "2025-04-01" } },
{ "Task.due_date": { "lte": "2025-04-30" } }
]
}
{
"and": [
{ "has_tag": "Book" },
{ "search": "machine learning" }
]
}
{
"or": [
{ "Task.status": { "match": "Blocked" } },
{ "Task.priority": { "match": "Critical" } }
]
}

6. Tasks whose status is at least InProgress

Section titled “6. Tasks whose status is at least InProgress”
{
"and": [
{ "has_tag": "Task" },
{ "Task.status": { "select_gte": "InProgress" } }
]
}

Reference fields create relationships between thogits. The filter DSL can follow these references using -> notation to filter by properties of the referenced thogit.

SourceTag.ref_field->TargetTag.field

The left side (SourceTag.ref_field) must be a Reference field. The right side is a filter applied to the thogit that the reference points to.

Example: Tasks assigned to a specific team

Section titled “Example: Tasks assigned to a specific team”

Suppose you have:

  • A “Task” tag with an assignee Reference field pointing to a person thogit
  • A “Person” tag with a team String field

Find all tasks assigned to someone on the “Platform” team:

{
"and": [
{ "has_tag": "Task" },
{ "Task.assignee->Person.team": "Platform" }
]
}

This filter:

  1. Looks at each thogit’s Task.assignee field (a ULID reference)
  2. Follows the reference to load the target thogit
  3. Checks that the target thogit’s Person.team field equals “Platform”

You can chain multiple hops with ->:

{ "Task.project_ref->Project.owner_ref->Person.team": "Platform" }

This follows Task.project_ref to a project thogit, then Project.owner_ref to a person thogit, and checks their team. The maximum traversal depth is 5 hops.

You can also filter on the referenced thogit’s name or description:

{ "Task.assignee->name": { "contains": "Alice" } }