kestra-io / kestra-io/client-sdk

Add complex query filter support (AND/OR + nested groups)

Open
#246 1 comment 0 reactions 1 assignee Claimed by @jymaire View on GitHub
area/plugin
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.