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).
Filter Types
Section titled “Filter Types”Full-text search
Section titled “Full-text search”Searches across both name and description fields (case-insensitive):
{ "search": "quarterly review" }Name filter
Section titled “Name filter”String filter applied to the thogit’s name:
{ "name": { "contains": "bug" } }Description filter
Section titled “Description filter”String filter applied to the thogit’s description:
{ "description": { "starts_with": "TODO" } }Tag presence
Section titled “Tag presence”Check whether a thogit has a specific tag applied. Accepts tag name or tag ID:
{ "has_tag": "Task" }{ "has_tag": "01JQA4N8E3KXYZ..." }Field value predicates
Section titled “Field value predicates”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" } }Logical operators
Section titled “Logical operators”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
Section titled “Operators”Operators determine how a field value is compared. The right-hand side of a dot-notation filter is always an operator expression.
Bare value shorthand
Section titled “Bare value shorthand”Bare values are shorthand for equality:
{ "Task.assignee": "01JQX..." }is equivalent to {"eq": "01JQX..."}.
| Bare Value | Equivalent To |
|---|---|
"text" | {"eq": "text"} |
42 | {"eq": 42} |
true | Boolean equality |
null | {"is_null": true} |
String operators
Section titled “String operators”| Operator | Description |
|---|---|
{"eq": "x"} | Exact match |
{"neq": "x"} | Not equal |
{"contains": "x"} | Substring match |
{"starts_with": "x"} | Prefix match |
{"matches": "^reg.*ex$"} | Regex match |
Number operators
Section titled “Number operators”| Operator | Description |
|---|---|
{"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
Section titled “Date operators”Date operators use the same keys as number operators but with date strings:
| Operator | Description |
|---|---|
{"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.
Existence operators
Section titled “Existence operators”| Operator | Description |
|---|---|
{"exists": true} | Field has a non-null value |
{"exists": false} | Field is null or missing |
{"is_null": true} | Field is null |
Set membership
Section titled “Set membership”{ "Task.priority": { "in": ["High", "Critical"] } }Matches if the field value is any of the listed values. Works with Select and MultiSelect fields too.
Select/MultiSelect operators
Section titled “Select/MultiSelect operators”| Operator | Description |
|---|---|
{"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 |
Progressive Examples
Section titled “Progressive Examples”1. Find all tasks
Section titled “1. Find all tasks”{ "has_tag": "Task" }2. Find tasks that are not done
Section titled “2. Find tasks that are not done”{ "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" } } ]}4. Search within a tag
Section titled “4. Search within a tag”{ "and": [ { "has_tag": "Book" }, { "search": "machine learning" } ]}5. Either/or conditions
Section titled “5. Either/or conditions”{ "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 Traversal
Section titled “Reference Traversal”Reference fields create relationships between thogits. The filter DSL can follow these references using -> notation to filter by properties of the referenced thogit.
Syntax
Section titled “Syntax”SourceTag.ref_field->TargetTag.fieldThe 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
assigneeReference field pointing to a person thogit - A “Person” tag with a
teamString field
Find all tasks assigned to someone on the “Platform” team:
{ "and": [ { "has_tag": "Task" }, { "Task.assignee->Person.team": "Platform" } ]}This filter:
- Looks at each thogit’s
Task.assigneefield (a ULID reference) - Follows the reference to load the target thogit
- Checks that the target thogit’s
Person.teamfield equals “Platform”
Chaining traversals
Section titled “Chaining traversals”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.
Traversal to name/description
Section titled “Traversal to name/description”You can also filter on the referenced thogit’s name or description:
{ "Task.assignee->name": { "contains": "Alice" } }