> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Searching in ClickHouse Observability and Elastic

> Compare Elastic search syntax with fully managed ClickHouse Observability, with notes for custom self-managed schemas.

## Search in ClickHouse Observability and Elastic

ClickHouse is a SQL-native engine, designed from the ground up for high-performance analytical workloads. In contrast, Elasticsearch provides a SQL-like interface, transpiling SQL into the underlying Elasticsearch query DSL — meaning it isn't a first-class citizen, and [feature parity](https://www.elastic.co/docs/explore-analyze/query-filter/languages/sql-limitations) is limited.

ClickHouse not only supports full SQL but extends it with a range of observability-focused functions, such as [`argMax`](https://clickhouse.com/docs/reference/functions/aggregate-functions/argMax), [`histogram`](https://clickhouse.com/docs/reference/functions/aggregate-functions/parametric-functions#histogram), and [`quantileTiming`](https://clickhouse.com/docs/reference/functions/aggregate-functions/quantileTiming), that simplify querying structured logs, metrics, and traces.

For simple log and trace exploration, the observability UI provides a [Lucene-style syntax](https://clickhouse.com/docs/clickstack/observability/features/search.md) for intuitive, text-based filtering for field-value queries, ranges, wildcards, and more. This is comparable to the [Lucene syntax](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-query-string-query#query-string-syntax) in Elasticsearch and elements of the [Kibana Query Language](https://www.elastic.co/docs/reference/query-languages/kql).

The search interface supports this familiar syntax but translates it behind the scenes into efficient SQL `WHERE` clauses, making the experience familiar for Kibana users while still allowing users to leverage the power of SQL when needed. This allows you to exploit the full range of [string search functions](https://clickhouse.com/docs/reference/functions/regular-functions/string-search-functions.md), [similarity functions](https://clickhouse.com/docs/reference/functions/regular-functions/string-functions.md#stringJaccardIndex) and [date time functions](https://clickhouse.com/docs/reference/functions/regular-functions/date-time-functions.md) in ClickHouse.

The search syntax below applies to both managed and self-managed services. Field names depend on your schema; the examples use standard OpenTelemetry log fields where applicable.

## ClickHouse Observability search syntax vs Elasticsearch query string

Both ClickHouse Observability and Elasticsearch provide flexible query languages to enable intuitive log and trace filtering. While Elasticsearch's query string is tightly integrated with its DSL and indexing engine, ClickHouse Observability supports a Lucene-inspired syntax that translates to ClickHouse SQL under the hood. The table below outlines how common search patterns behave across both systems, highlighting similarities in syntax and differences in backend execution.

| **Feature** | **ClickHouse Observability Syntax** | **Elasticsearch Syntax** | **Comments** |
| - | - | - | - |
| Free text search | `error` | `error` | ClickHouse Observability searches the source's configured full-text expression, commonly `Body`, with case-insensitive whole-word matching by default. It does not automatically search every column. |
| Field match | `SeverityText:error` | `level:error` | Use the field name from your schema. In ClickHouse Observability, unquoted string field searches match substrings; quote the value for equality, for example `SeverityText:"error"`. |
| Phrase search | `"disk full"` | `"disk full"` | Matches the phrase in the configured full-text expression. |
| Field phrase match | `Body:"disk full"` | `message:"disk full"` | In ClickHouse Observability, a directly quoted field value uses equality: this matches the entire body, not a phrase within a longer message. |
| OR conditions | `error OR warning` | `error OR warning` | Logical OR of terms; both systems support this natively. |
| AND conditions | `error AND db` | `error AND db` | Both translate to intersection; no difference in user syntax. |
| Negation | `NOT error` or `-error` | `NOT error` or `-error` | Excludes matching events. |
| Grouping | `(error OR fail) AND db` | `(error OR fail) AND db` | Standard Boolean grouping in both. |
| Wildcards | `error*` or `*fail*` | `error*`, `*fail*` | ClickHouse Observability supports leading and trailing wildcards, including in free-text searches; internal wildcards such as `f*ail` are not supported. Elasticsearch allows leading wildcards by default, but they can be disabled and can be expensive. |
| Ranges (numeric/date) | `Duration:[100 TO 200]` | `duration:[100 TO 200]` | Square brackets include both bounds. Use the field name and units from your schema. |
| Unbounded ranges (numeric/date) | `Duration:>10` or `Duration:>=10` | `duration:>10` or `duration:>=10` | Comparison operators express open-ended ranges. |
| Inclusive/exclusive | `Duration:{100 TO 200}` | `duration:{100 TO 200}` | Curly braces exclude both bounds. |
| Exists check | `LogAttributes.log.file.path:*` | `_exists_:user` or `field:*` | For a string-valued `Map` attribute, ClickHouse Observability checks for a non-empty value. Use SQL `mapContains` if you need key presence regardless of value; see [Schema and missing fields](#empty-value-differences-self-configured). |
| Regex | `match` function | `name:/joh?n(ath[oa]n)/` | Not currently supported in Lucene syntax. You can use SQL and the [`match`](https://clickhouse.com/docs/reference/functions/regular-functions/string-search-functions#match) function or other [string search functions](https://clickhouse.com/docs/reference/functions/regular-functions/string-search-functions.md). |
| Fuzzy match | `editDistance('quikc', field) = 1` | `quikc~` | Not currently supported in Lucene syntax. Distance functions can be used in SQL e.g. `editDistance('rror', SeverityText) = 1` or [other similarity functions](https://clickhouse.com/docs/reference/functions/regular-functions/string-functions.md#jaroSimilarity). |
| Proximity search | Not supported | `"fox quick"~5` | Not currently supported in Lucene syntax. |
| Boosting | Not supported | `quick^2 fox` | Not supported in ClickHouse Observability at present. |
| Field wildcard | Not supported | `service.*:error` | Not supported in ClickHouse Observability at present. |
| Escaped special chars | Escape reserved characters with `\` | Same | Escaping required for reserved symbols. |

## Schema and missing fields

The standard OpenTelemetry schema uses fields such as `Body`, `SeverityText`, and `ServiceName`, with log and resource attributes in `LogAttributes` and `ResourceAttributes`. Translate Elastic field names to the corresponding fields in your ingested data—for example, `level:error` becomes `SeverityText:error`.

For non-nullable columns, an omitted value is represented by the column's default, such as an empty string. An empty `ServiceName` therefore does not tell you whether the sender omitted the value or explicitly sent an empty string.

For self-managed deployments with custom tables, use your column names and check their defaults and nullability. [`Nullable`](https://clickhouse.com/docs/reference/data-types/nullable) columns can contain `NULL`.

For SQL queries, `ServiceName != ''` checks for a non-empty service name. Attributes stored in a `Map` are distinct from top-level columns: use `mapContains(LogAttributes, 'log.file.path')` to check whether an attribute key exists, including when its value is empty.
