Combine and reuse ES|QL queries

ES|QL provides several ways to combine, filter, and reuse query results beyond querying a single index. Choose the mechanism that best fits your goal.

Mechanism What it does When to use
Subquery Nests a query inside another query, either to combine result sets or to filter or evaluate rows You need to use the results of one query inside another
View Saves a named query as a virtual index that any FROM can reference You want to define a query once and reuse it across multiple requests
FORK Sends the same incoming rows through multiple independent branches You want to run different processing on the same data in one query

Views, FROM subqueries, IN subqueries, and FORK share several traits but differ in important ways.

IN subqueries operate differently from the other three. They filter rows rather than producing branches, so the similarities and differences below apply to FROM subqueries, views, and FORK only.

  • Dynamic execution. All three run at query time, so results reflect the current state of the data.
  • Union of columns. Columns from multiple branches are merged into a single table. Missing columns are filled with null values.
  • Supported commands. Complex processing commands can be used inside both views and FROM subqueries, as detailed in the description of FROM subqueries.
  • Nested branching. Support depends on the version.

Views, FROM subqueries, and FORK can be nested. The complete query remains subject to the branch and command limits.

Nested branching is generally not supported. Views can use query compaction when the nested branches can be flattened into one branch point.

  • Branch limits. The limits depend on the branching mechanism and version:
  • Maximum branch count. A single FORK is capped at 8 branches by default (esql.query.max_branch_count_per_merge).
  • View query compaction flattens nested view unions only when the flat width is within esql.query.max_branch_count (20 by default). The same setting caps nested leaves across the whole query.
  • Maximum branch level. Nested branch points created by views, FROM subqueries, and FORK are capped at 5 levels by default (esql.query.max_branch_level). This limit counts nested branch points, not view nesting depth.
  • Maximum branch count. FORK is capped at 8 branches.
  • Views are capped at 8 branches.
  • FORK does not include a source command. Every branch receives the same incoming rows and columns.
  • FROM subqueries and views each have their own source command (FROM, TS, or ROW), so branches can read from different sources with different columns.

A query can use multiple FORK commands when views or multi-source FROM commands create separate source branches, but each uninterrupted pipeline can contain only one. Refer to the FORK limitations for supported patterns and examples.

Only one FORK command is allowed per query, so nested branches aren't possible. FROM subqueries and views have similar restrictions, but views can sometimes flatten nested branches through query compaction.

  • Views must be defined using the REST API before they can be used in queries. Subqueries are written inline and require no setup.
  • Views have names that are unique within the index namespace. A view cannot share a name with an index.
  • Views can be nested up to a depth of 10. Cyclic references are not allowed. For example, if viewA references viewB and viewB references viewC, then viewC cannot reference viewA. Cycles are detected at query time.

FROM subqueries and views can contain further FROM subqueries and FORK commands, subject to the branching limits.

No more than one branch point can exist across a view nesting chain. FROM subqueries don't support further FROM subqueries or FORK inside them, but they can contain IN subqueries. Views allow nested branching under limited conditions.

Depending on your goal, one of these alternatives may be a better fit:

  • LOOKUP JOIN: enrich rows by joining against a lookup index on a key field.
  • ENRICH: augment rows with data from an enrich policy.
  • Query multiple indices: use comma-separated index patterns or wildcards in a single FROM to query across indices without subqueries.