Chris Collins

Tools · search

Query DSL builder and explainer

Build Elasticsearch and OpenSearch queries in a form or as JSON — each edits the other — and see them explained in plain English (query vs filter context, minimum_should_match, the Lucene query they become), linted for slow or surprising patterns, and run against a sample index in your browser with hits, scores, explanations, highlights and aggregations; optionally send them read-only to your own cluster.

Added

How to use it

How to use it

Pick an example or start from the form. The Build tab has the form and the JSON side by side: change either and the other follows; anything the form has no editor for stays as JSON and is kept. Below them, the first hits, any aggregations and the important lints update as you type.

The form covers bool (must, should, filter, must_not, minimum_should_match), match, match_phrase, match_phrase_prefix, match_bool_prefix, multi_match (all types), query_string, simple_query_string, term, terms, range, exists, ids, prefix, wildcard, regexp, fuzzy, constant_score, dis_max, boosting, function_score, script_score, nested and knn; paging, sorting, search_after, highlighting, _source and track_total_hits; and aggregations (terms, histogram, date_histogram, range, date_range, cardinality, percentiles, avg/sum/min/max/stats/value_count, top_hits, nested, reverse_nested, global, filter) with sub-aggregations.

Explain describes the request clause by clause, marking query context (scored) and filter context (yes/no, cacheable); shows the Lucene query it becomes (+name:wireless #in_stock:true, (a | b)~0.3, Synonym(…)); lists the lints; has a minimum_should_match calculator (try 2<75% or 2←25% 9←3 and see how many clauses each count requires); and compares from/size, search_after and point in time.

Results lists every hit with its score and highlights — click one for its explanation tree (what _explain returns) and _source — renders the aggregations as bars, and shows the raw response. Sample index shows the mapping and documents, with an _analyze box per field.

Your cluster sends the same request to a real Elasticsearch or OpenSearch with POST _search, _explain/<id> or _analyze — read-only endpoints only — and shows the cluster’s answer beside the toy engine’s.

Lints

Leading wildcards and .* regexps (full term-dictionary scans); from + size beyond 10,000 (an error) or deep pagination; search_after without a tiebreaker or a point in time; term queries on analyzed text fields; queries on nested fields outside a nested query; sorting or aggregating on text fields (fielddata); high-cardinality terms aggregations; scripts; optional should clauses next to must; simple_query_string negation with the default OR; mixed AND/OR in query_string; match_phrase_prefix expansion limits; and notes on HyperLogLog++ (cardinality), t-digest (percentiles) and per-shard terms counts.

What the engine does

The toy engine is the same as in the scoring explainer: one shard, BM25 as Elasticsearch computes it, the analyzers of the analyzer playground, minimum_should_match exactly as Elasticsearch parses it (including its float rounding), Lucene’s classic query-string parser (with its a OR b AND c → a +b +c quirk), Lucene’s simple query parser, Elasticsearch date math (now-1d/d, ||+1M, rounding up for gt/lte), sloppy phrases, fuzzy expansion (AUTO = 0/1/2 edits by length, transpositions, blended document frequency), nested documents as hidden documents, and the documented error messages for common mistakes (result window too large, fielddata disabled, unknown query).

Limits

  • A teaching model of one shard, in your browser. It is not Elasticsearch: query types and options outside the list above are kept in the JSON but return "not modelled" when run (for example geo, span, intervals, more_like_this, percolate, has_child, combined_fields, semantic and sparse vector queries, and pipeline aggregations).

  • knn is exact (every vector compared) and the vectors are a toy 8-dimension embedding. Elasticsearch searches an HNSW graph approximately, per shard, with num_candidates.

  • cardinality counts exactly and percentiles interpolates between sorted values; Elasticsearch uses HyperLogLog++ and t-digest, which are approximate on large data.

  • Highlighting marks every matching term in a sentence-sized fragment; Elasticsearch’s unified highlighter also restricts phrase queries to the matching phrase.

  • Dates are UTC (no time_zone); "now" is fixed at 2026-10-15 so examples are reproducible.

  • Your cluster: the browser only shows responses from clusters that allow this page’s origin (CORS: http.cors.enabled and http.cors.allow-origin). Credentials stay in memory for the tab and never go into links or storage; the URL and index are remembered locally but are not shared either.

Linking to an example

Links can be written by hand. Add the tab after #: build, explain, results, index or cluster. Requests you build travel in the link’s ?s= parameter; the cluster URL and credentials never do.

Parameter Meaning Example

set

The sample index: products or articles

set=articles

example

One of the requests below (it also picks its index)

example=msm

example= Shows

match

match: analyzed, an OR of the terms, scored by BM25 (open)

bool-filter

bool: must scores, filter only filters, should boosts; with highlighting (open)

msm

minimum_should_match "2<75%" on a five-term query (open)

multi-match

multi_match cross_fields with operator and (open)

phrase-slop

match_phrase with slop 4 (open)

query-string

query_string with fields, a range and negation (open)

simple-query-string

simple_query_string where "-studio" with the default OR matches nearly everything (open)

term-trap

term on a text field finds nothing (open)

nested

nested: the text and the stars must match in the same review, with inner_hits (open)

function-score

function_score: text × log1p(reviews) × recency (open)

aggs

terms with a sub-aggregation, histogram, date_histogram, percentiles, cardinality, nested (open)

search-after

the page after price 199 / id 5 with search_after (open)

deep-paging

from + size beyond 10,000 is rejected (open)

leading-wildcard

a leading wildcard scans every term (open)

knn

the three nearest toy vectors to "earbuds for the gym" (open)

hybrid-rrf

an rrf retriever fusing BM25 and kNN (open)

recency

articles: relevance × a gauss decay on the publish date (open)

Runs entirely in your browser — network requests go only to the services named on this page.