Skip to main content
Skip to main content

Searching in ClickStack and Elastic

Search in ClickStack 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 is not a first-class citizen, and feature parity is limited.

ClickHouse not only supports full SQL but extends it with a range of observability-focused functions, such as argMax, histogram, and quantileTiming, that simplify querying structured logs, metrics, and traces.

For simple log and trace exploration, HyperDX provides a Lucene-style syntax for intuitive, text-based filtering for field-value queries, ranges, wildcards, and more. This is comparable to the Lucene syntax in Elasticsearch and elements of the Kibana Query Language.

HyperDX's 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 users to exploit the full range of string search functions, similarity functions and date time functions in ClickHouse.

Below, we compare the Lucene query languages of ClickStack and Elasticsearch.

ClickStack search syntax vs Elasticsearch query string

Both HyperDX 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, HyperDX 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.

FeatureHyperDX SyntaxElasticsearch SyntaxComments
Free text searcherrorerrorMatches across all indexed fields; in ClickStack this is rewritten to a multi-field SQL ILIKE.
Field matchlevel:errorlevel:errorIdentical syntax. HyperDX matches exact field values in ClickHouse.
Phrase search"disk full""disk full"Quoted text matches an exact sequence; ClickHouse uses string equality or ILIKE.
Field phrase matchmessage:"disk full"message:"disk full"Translates to SQL ILIKE or exact match.
OR conditionserror OR warningerror OR warningLogical OR of terms; both systems support this natively.
AND conditionserror AND dberror AND dbBoth translate to intersection; no difference in user syntax.
NegationNOT error or -errorNOT error or -errorSupported identically; HyperDX converts to SQL NOT ILIKE.
Grouping(error OR fail) AND db(error OR fail) AND dbStandard Boolean grouping in both.
Wildcardserror* or *fail*error*, *fail*HyperDX supports leading/trailing wildcards; ES disables leading wildcards by default for perf. Wildcards within terms are not supported, e.g., f*ail. Wildcards must be applied with a field match.
Ranges (numeric/date)duration:[100 TO 200]duration:[100 TO 200]HyperDX uses SQL BETWEEN; Elasticsearch expands to range queries. Unbounded * in ranges are not supported e.g. duration:[100 TO *]. If needed use Unbounded ranges below.
Unbounded ranges (numeric/date)duration:>10 or duration:>=10duration:>10 or duration:>=10HyperDX uses standard SQL operators
Inclusive/exclusiveduration:{100 TO 200} (exclusive)SameCurly brackets denote exclusive bounds. * in ranges are not supported. e.g. duration:[100 TO *]
Exists checkN/A_exists_:user or field:*_exists_ is not supported. Use LogAttributes.log.file.path: * for Map columns e.g. LogAttributes. For root columns, these have to exist and will have a default value if not included in the event. To search for default values or missing columns use the same syntax as Elasticsearch ServiceName:* or ServiceName != ''.
Regexmatch functionname:/joh?n(ath[oa]n)/Not currently supported in Lucene syntax. Users can use SQL and the match function or other string search functions.
Fuzzy matcheditDistance('quikc', field) = 1quikc~Not currently supported in Lucene syntax. Distance functions can be used in SQL e.g. editDistance('rror', SeverityText) = 1 or other similarity functions.
Proximity searchNot supported"fox quick"~5Not currently supported in Lucene syntax.
Boostingquick^2 foxquick^2 foxNot supported in HyperDX at present.
Field wildcardservice.*:errorservice.*:errorNot supported in HyperDX at present.
Escaped special charsEscape reserved characters with \SameEscaping required for reserved symbols.

Exists/missing differences

Unlike Elasticsearch, where a field can be entirely omitted from an event and therefore truly "not exist," ClickHouse requires all columns in a table schema to exist. If a field is not provided in an insert event:

  • For Nullable fields, it will be set to NULL.
  • For non-nullable fields (the default), it will be populated with a default value (often an empty string, 0, or equivalent).

In ClickStack, we use the latter as Nullable is not recommended.

This behavior means that checking whether a field "exists”" in the Elasticsearch sense is not directly supported.

Instead, users can use field:* or field != '' to check for the presence of a non-empty value. It is thus not possible to distinguish between truly missing and explicitly empty fields.

In practice, this difference rarely causes issues for observability use cases, but it's important to keep in mind when translating queries between systems.