# FuseQL Subquery Operators

The `subquery` and `compose` operators enable dynamic filtering when you don’t know the exact filter criteria upfront. The inner query runs first to discover filter values, which are then applied to the outer query.

## compose

Convert query results into a FuseQL filter expression. Primarily used within `subquery`, but can be run standalone to preview the generated filter.

### _Syntax_

```
| compose <field1>[, <field2>, ...] [maxresults=<N>] [keywords]
```

| Parameter          | Description                                                                                          |
|--------------------|------------------------------------------------------------------------------------------------------|
| `<fields>`         | Required. One or more field names to use for filter generation. Multiple fields create AND conditions within each row. |
| `maxresults=<N>`   | Optional. Limits results used in filter (default: 2500, max: 10000).                                |
| `keywords`         | Optional. Generates grep searches instead of field=value filters.                                   |

### _Filter Format_

Given this input table:

| field1 | field2 |
|--------|--------|
| value1 | value2 |
| value3 | value4 |

Running `| compose field1, field2` produces:

Without `keywords`:

```
((field1="value1" and field2="value2") or (field1="value3" and field2="value4"))
```

With `keywords`:

```
(("value1" and "value2") or ("value3" and "value4"))
```

### _Example_

Generate a filter from error levels and orgs:

```
source="query-service" | count by level, org_id | compose level, org_id
```

Input table (from `count by level, org_id`):

| level | org_id         | _count |
|-------|----------------|--------|
| error | pisco-shared   | 150    |
| info  | pisco-shared   | 320    |

Result from the compose operator:

```
((level="error" and org_id="pisco-shared") or (level="info" and org_id="pisco-shared"))
```

### _Common Use Cases_

- Debug subqueries by previewing the generated filter
- Verify filter size before applying to large datasets
- Generate allowlist/blocklist filters from known entities

## subquery

Execute a nested query and use its results as a dynamic filter in the outer query.

|     |     |
|-----|-----|
|     | The `subquery` operator must always include a `compose` operator as its final stage. |

### _Syntax_

```
[subquery: <inner_query> | compose <fields> [maxresults=<N>] [keywords]]
```

The subquery can be used at the start of a query, within a `where` clause, or in an `if` operator:

```
[subquery: <inner_query> | compose <fields>] | <outer_query>

<outer_query> | where [subquery: <inner_query> | compose <fields>]

<outer_query> | if([subquery: <inner_query> | compose <fields>], <true_value>, <false_value>) as <field>
```

|     |     |
|-----|-----|
|     | The `keywords` clause is not supported with `where` and `if` operations. |

### _Behavior_

1. Executes the inner query first
2. Uses `compose` to transform results into a filter expression
3. Applies the generated filter to the outer query

### _Example_

Filter logs by top hosts from another source:

```
org_id="pisco-shared" and [subquery: source="query-service" | count by host | compose host] | timeslice 20s | count by _timeslice
```

The inner query `source="query-service" | count by host` returns:

| host      | _count |
|-----------|--------|
| server-1  | 250    |
| server-2  | 180    |

The `compose host` operator converts this to `((host="server-1") or (host="server-2"))`, making the query equivalent to:

```
org_id="pisco-shared" and ((host="server-1") or (host="server-2")) | timeslice 20s | count by _timeslice
```

### _Common Use Cases_

- Correlate errors across multiple services by user or session
- Find slow services and investigate their log patterns
- Filter one data source based on patterns discovered in another

### _Limitations_

Subqueries are not supported in Scheduled Views.

### _Notes_

- The outer query can be any query that returns results. Always test it before you add the inner query.
- Subqueries within `if` or `where` are typically more expensive than when run as part of the search expression.
