Numbers, Booleans and Dates
"Books under 15 that are in stock, published in the last five years." Every part of that request depends on three field types being mapped correctly: numeric, boolean and date. Get them right and the filter is fast and exact; get them wrong and it quietly misbehaves.
The rule
Pick the smallest type that safely fits; dates are stored as instants in UTC.
Numeric types come in whole and decimal families:
| Type | Holds |
|---|---|
byte, short, integer, long |
Whole numbers, growing range (long is 64-bit) |
float, half_float, double |
Decimals, with 32-, 16- and 64-bit precision |
scaled_float |
A decimal stored as a whole number times a fixed scaling_factor |
For money, scaled_float with "scaling_factor": 100 stores 12.5 as 1250 — exact to the cent and compact. Page counts fit in integer. Smaller types save disk, but only if every value fits.
Boolean holds true or false. It also accepts the strings "true" and "false", but nothing else — "yes" or 1 is rejected.
Date fields accept a date string, a date-time string, or a number of milliseconds since the epoch. Internally each date becomes one instant in UTC, so comparisons are exact. The default format accepts ISO strings such as "2019-04-02" and "2019-04-02T10:30:00Z"; you can declare your own:
"published": { "type": "date", "format": "yyyy-MM-dd||epoch_millis" }Numbers and dates are what range queries and date math work on:
GET /books/_search
{
"query": { "range": { "published": { "gte": "now-5y/d" } } }
}now-5y/d means "five years ago, rounded down to the start of that day".
The shortcut
For each field ask two questions: "whole or decimal?" then "what is the largest value it will ever hold?" For dates, ask "do I know the time zone?" — if a value has no zone, it is read as UTC.
pages
Whole, never above a few thousand →
integer.
The trap: storing numbers as keyword. They then sort as text, so "100" comes before "20", and range queries compare them letter by letter.
Drills
Answer fast — trust the rule.
Which value is rejected by a boolean field?
A price of 12.5 goes into scaled_float with scaling_factor: 100. How is it stored?
A date is sent as "2023-01-20T09:00:00" with no time zone. How is it interpreted?
Prices were mapped as keyword. Sorting ascending gives "100", "20", "9.99". Why?
Remember
- Pick the smallest type that safely fits; dates are stored as instants in UTC.
- Whole or decimal? Largest value? Known time zone?
- Numbers stored as keyword sort and compare like text.
