kestra-io / kestra-io/client-sdk
Add complex query filter support (AND/OR + nested groups)
- Dominant language
- Java
- Stars
- 18
- Forks
- 5
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 40
Description
# Description
Kestra core PR [#16197](https://github.com/kestra-io/kestra/pull/16197) introduced **complex condition-group support** for the `filters[...]` query parameters used by every `*ByQuery` / search endpoint.
The backend now accepts:
- `AND` / `OR` groups
- one level of nesting
- fully backward-compatible flat filters
The client SDKs currently expose only the flat filter shape (a list of single `field/op/value` filters). This issue tracks adding **first-class support for grouped and nested queries** in:
- Python
- Java
- Go
- JavaScript
The goal is to allow SDK users to construct the same queries the UI now produces **without manually encoding query strings**.
---
# API Query Shape
As introduced in [#16197](https://github.com/kestra-io/kestra/pull/16197), repeated `filters[...]` keys encode boolean structure through bracketed segments.
## Flat Filters (Legacy)
This format must continue to work unchanged.
```
filters[flowId][EQUALS]=flow-id
```
## Top-Level `AND` Group
```
filters[and][0][namespace][EQUALS]=ns
filters[and][1][flowId][EQUALS]=f
```
## Top-Level `OR` Group
```
filters[or][0][scope][EQUALS]=s1
filters[or][1][scope][EQUALS]=s2
```
## Nested Groups (One Level)
Example: `AND` containing an `OR`.
```
filters[and][0][namespace][EQUALS]=ns
filters[and][1][or][0][scope][EQUALS]=s1
filters[and][1][or][1][scope][EQUALS]=s2
```
---
# Serialization Rules
Each leaf node follows this structure:
```
filters[][]=value
```
Where:
- `` uses `camelCase`
- `` is uppercase
## Special Cases
| Logical Field | Serialized Name |
| --- | --- |
| `QUERY` | `q` |
| `MIN_LEVEL` | `level` |
## Value Encoding
| Operator / Type | Encoding |
| --- | --- |
| `IN` / `NOT_IN` | CSV values |
| `Map` values | `[key]` suffixes |
| `LABELS` | Uses map-style serialization |
---
# Proposed User-Facing API
A jOOQ-style DSL has already been prototyped for Java on the local `feat/complex-query-java` branch.
Other SDKs should implement idiomatic equivalents.
## Java Prototype
```java
import static io.kestra.sdk.query.Query.*;
List filters = where(
and(
eq(QueryFilterField.FLOW_ID, "flow-id"),
or(
eq(QueryFilterField.SCOPE, "scope-1"),
eq(QueryFilterField.SCOPE, "scope-2")
)
)
);
client.executions().searchExecutions(/* ..., */ filters);
```
---
# Proposed SDK Design
The Java prototype consists of three primary pieces that other SDKs should mirror.
## 1. Query AST
A minimal abstract syntax tree:
- `Leaf(field, op, value)`
- `Node(AND | OR, children[])`
## 2. Builder / DSL
### Core Builders
- `filter(...)`
- `and(...)`
- `or(...)`
- `where(root)`
### Convenience Helpers
- `eq`
- `notEq`
- `in`
- `notIn`
- `contains`
- `startsWith`
- `endsWith`
- `regex`
- `prefix`
- `greaterThan`
- `greaterThanOrEqual`
- `lessThan`
- `lessThanOrEqual`
### Important Behavior
`where(root)` should flatten a top-level `AND` so existing filter parameters continue producing the same wire format as today.
## 3. Serializer
A serializer walks the query tree and emits the bracketed query-parameter pairs required by the API.
Example output:
```
filters[and][1][or][0][scope][EQUALS]=s1
```
---
# Backward Compatibility Requirements
Existing flat-list usage must continue to work exactly as today.
Examples:
```java
List.of(filter1, filter2)
```
Or equivalent SDK-native forms in other languages.
Top-level `AND` groups should serialize to the same wire format currently produced by flat filter lists.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.