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).
-
knnis exact (every vector compared) and the vectors are a toy 8-dimension embedding. Elasticsearch searches an HNSW graph approximately, per shard, withnum_candidates. -
cardinalitycounts exactly andpercentilesinterpolates 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.enabledandhttp.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.
Related: Analyzer playground, Scoring explainer, JSON tools, Regex tester, Postgres, Redis.
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 |
|---|---|---|
|
The sample index: |
|
|
One of the requests below (it also picks its index) |
|
example= |
Shows |
|---|---|
|
match: analyzed, an OR of the terms, scored by BM25 (open) |
|
bool: must scores, filter only filters, should boosts; with highlighting (open) |
|
minimum_should_match "2<75%" on a five-term query (open) |
|
multi_match cross_fields with operator and (open) |
|
match_phrase with slop 4 (open) |
|
query_string with fields, a range and negation (open) |
|
simple_query_string where "-studio" with the default OR matches nearly everything (open) |
|
term on a text field finds nothing (open) |
|
nested: the text and the stars must match in the same review, with inner_hits (open) |
|
function_score: text × log1p(reviews) × recency (open) |
|
terms with a sub-aggregation, histogram, date_histogram, percentiles, cardinality, nested (open) |
|
the page after price 199 / id 5 with search_after (open) |
|
from + size beyond 10,000 is rejected (open) |
|
a leading wildcard scans every term (open) |
|
the three nearest toy vectors to "earbuds for the gym" (open) |
|
an rrf retriever fusing BM25 and kNN (open) |
|
articles: relevance × a gauss decay on the publish date (open) |
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser — network requests go only to the services named on this page.