Range query #
Returns documents that contain terms within a provided range.
Use it for intervals: prices between two numbers, events inside a time window, names inside an alphabetical span — anything expressible as “from / to” bounds rather than a list of exact values.
Inside a
nestedquery: supported — the bounds apply per array element.
How it works #
The engine picks the index by field type:
- Numeric and
datefields — the per-field BKD range index (or the column store’s value-sorted region on merged segments without a BKD index). The BKD traversal returns an exact, pre-computed document-id list — no posting verification, no false positives. Date bounds go through the engine’s date parser: epoch numerics parse as epoch milliseconds, and ISO-8601 strings (2024-06-01,2024-06-01T00:00:00Z) parse to their UTC instant before the traversal. keyword/textfields — a lexicographic term range over the ordered dictionary: every term between the bounds is expanded and their postings unioned, exactly like ashouldoftermqueries. Bounds are first run through the field’s normalizer, if one is mapped, sodate-descendingkeys sort as they were indexed.
Dual bounds conjoin. When you send both gt and gte (or both
lt and lte), the engine applies them conjunctively and keeps the
tighter bound — a tie resolves to the exclusive variant, so
gt: 100, gte: 150 reads as ≥ 150. At most one bound per side is
usually written; the conjoin exists so machine-generated bodies that
carry both still behave deterministically.
Scoring. Range matches carry a constant score — the boost
(1.0 by default) — with no BM25 input. A range is therefore the
natural shape for bool.filter clauses: sliding time windows and
price bands constrain the candidate set without touching relevance.
Date knobs. format and time_zone are accepted on the wire for
compatibility; today the engine parses bounds with its
built-in date parser and does not yet apply these two knobs.
Examples #
The following search returns the sales whose price is between 45 and
60 — 20 of the 120 documents in the sales dataset.
GET /_search
{
"query": {
"range": {
"field": "age",
"gte": 10,
"lte": 20
}
}
}
Use cases #
- Time windows.
sales.date ≥ 2025-01-01returns the 28 newest sales of 120 — the rolling-window filter behind every “last N months” dashboard.customers.since ≥ 2025-01-01scopes to the 7 newest customers of 20. - Price bands.
price ≤ 30oversalesmatches the 90 economy sales (60 at 15, 30 at 30); pair one range with atermsonstatusfor segmented funnels. - Lexicographic spans. Over keyword fields the same query slices
alphabetically —
idranges,A*–M*name partitions — through the dictionary walk described above. - Alerting thresholds. Latency or disk-usage bounds as a
must_not.range(the violation detector) inside a monitoringbool.
Parameters for range
#
field
(Required, string) Field you wish to search.gt
(Optional) Greater than.gte
(Optional) Greater than or equal to.lt
(Optional) Less than.lte
(Optional) Less than or equal to.format
(Optional, string) Date format for date-field range bounds. Accepted for body compatibility; not yet applied.time_zone
(Optional, string) Time zone for date-field range bounds, e.g.+08:00. Accepted for body compatibility; not yet applied.boost
(Optional, float, default:1.0) Decrease or increase the relevance scores of the query.relation
(Optional, string) How the range matchesrange-typed fields:INTERSECTS(default),CONTAINS, orWITHIN.
Related #
rangeaggregation — bucket the same field into named intervals; the query filters, the aggregation counts.date_range/date_histogramaggregations — time-bucketed views of the date windows a range query filters on.term— the single-point special case, served by the same BKD index on numeric and date fields.exists— the boundless question: does the field carry any value at all?