Range field types
editRange field types
editRange field types represent a continuous range of values between an upper and lower
bound. For example, a range can represent any date in October or any
integer from 0 to 9. They are defined using the operators
gt
or gte
for the lower bound, and lt
or lte
for the upper bound.
They can be used for querying, and have
limited support for aggregations. The only supported aggregations are
histogram,
cardinality.
The following range types are supported:
|
A range of signed 32-bit integers with a minimum value of |
|
A range of single-precision 32-bit IEEE 754 floating point values. |
|
A range of signed 64-bit integers with a minimum value of |
|
A range of double-precision 64-bit IEEE 754 floating point values. |
|
A range of |
|
A range of ip values supporting either IPv4 or IPv6 (or mixed) addresses. |
Below is an example of configuring a mapping with various range fields followed by an example that indexes several range types.
resp = client.indices.create( index="range_index", settings={ "number_of_shards": 2 }, mappings={ "properties": { "expected_attendees": { "type": "integer_range" }, "time_frame": { "type": "date_range", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" } } }, ) print(resp) resp1 = client.index( index="range_index", id="1", refresh=True, document={ "expected_attendees": { "gte": 10, "lt": 20 }, "time_frame": { "gte": "2015-10-31 12:00:00", "lte": "2015-11-01" } }, ) print(resp1)
response = client.indices.create( index: 'range_index', body: { settings: { number_of_shards: 2 }, mappings: { properties: { expected_attendees: { type: 'integer_range' }, time_frame: { type: 'date_range', format: 'yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis' } } } } ) puts response response = client.index( index: 'range_index', id: 1, refresh: true, body: { expected_attendees: { gte: 10, lt: 20 }, time_frame: { gte: '2015-10-31 12:00:00', lte: '2015-11-01' } } ) puts response
const response = await client.indices.create({ index: "range_index", settings: { number_of_shards: 2, }, mappings: { properties: { expected_attendees: { type: "integer_range", }, time_frame: { type: "date_range", format: "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis", }, }, }, }); console.log(response); const response1 = await client.index({ index: "range_index", id: 1, refresh: "true", document: { expected_attendees: { gte: 10, lt: 20, }, time_frame: { gte: "2015-10-31 12:00:00", lte: "2015-11-01", }, }, }); console.log(response1);
PUT range_index { "settings": { "number_of_shards": 2 }, "mappings": { "properties": { "expected_attendees": { "type": "integer_range" }, "time_frame": { "type": "date_range", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" } } } } PUT range_index/_doc/1?refresh { "expected_attendees" : { "gte" : 10, "lt" : 20 }, "time_frame" : { "gte" : "2015-10-31 12:00:00", "lte" : "2015-11-01" } }
|
|
Example indexing a meeting with 10 to 20 attendees, not including 20. |
|
Example date range using date time stamp. |
The following is an example of a term query on the integer_range
field named "expected_attendees".
12 is a value inside the range, so it will match.
resp = client.search( index="range_index", query={ "term": { "expected_attendees": { "value": 12 } } }, ) print(resp)
response = client.search( index: 'range_index', body: { query: { term: { expected_attendees: { value: 12 } } } } ) puts response
const response = await client.search({ index: "range_index", query: { term: { expected_attendees: { value: 12, }, }, }, }); console.log(response);
GET range_index/_search { "query" : { "term" : { "expected_attendees" : { "value": 12 } } } }
The result produced by the above query.
{ "took": 13, "timed_out": false, "_shards" : { "total": 2, "successful": 2, "skipped" : 0, "failed": 0 }, "hits" : { "total" : { "value": 1, "relation": "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "range_index", "_id" : "1", "_score" : 1.0, "_source" : { "expected_attendees" : { "gte" : 10, "lt" : 20 }, "time_frame" : { "gte" : "2015-10-31 12:00:00", "lte" : "2015-11-01" } } } ] } }
The following is an example of a date_range
query over the date_range
field named "time_frame".
resp = client.search( index="range_index", query={ "range": { "time_frame": { "gte": "2015-10-31", "lte": "2015-11-01", "relation": "within" } } }, ) print(resp)
response = client.search( index: 'range_index', body: { query: { range: { time_frame: { gte: '2015-10-31', lte: '2015-11-01', relation: 'within' } } } } ) puts response
const response = await client.search({ index: "range_index", query: { range: { time_frame: { gte: "2015-10-31", lte: "2015-11-01", relation: "within", }, }, }, }); console.log(response);
GET range_index/_search { "query" : { "range" : { "time_frame" : { "gte" : "2015-10-31", "lte" : "2015-11-01", "relation" : "within" } } } }
Range queries work the same as described in range query. |
|
Range queries over range fields support a |
This query produces a similar result:
{ "took": 13, "timed_out": false, "_shards" : { "total": 2, "successful": 2, "skipped" : 0, "failed": 0 }, "hits" : { "total" : { "value": 1, "relation": "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "range_index", "_id" : "1", "_score" : 1.0, "_source" : { "expected_attendees" : { "gte" : 10, "lt" : 20 }, "time_frame" : { "gte" : "2015-10-31 12:00:00", "lte" : "2015-11-01" } } } ] } }
IP Range
editIn addition to the range format above, IP ranges can be provided in CIDR notation:
resp = client.indices.put_mapping( index="range_index", properties={ "ip_allowlist": { "type": "ip_range" } }, ) print(resp) resp1 = client.index( index="range_index", id="2", document={ "ip_allowlist": "192.168.0.0/16" }, ) print(resp1)
response = client.indices.put_mapping( index: 'range_index', body: { properties: { ip_allowlist: { type: 'ip_range' } } } ) puts response response = client.index( index: 'range_index', id: 2, body: { ip_allowlist: '192.168.0.0/16' } ) puts response
const response = await client.indices.putMapping({ index: "range_index", properties: { ip_allowlist: { type: "ip_range", }, }, }); console.log(response); const response1 = await client.index({ index: "range_index", id: 2, document: { ip_allowlist: "192.168.0.0/16", }, }); console.log(response1);
PUT range_index/_mapping { "properties": { "ip_allowlist": { "type": "ip_range" } } } PUT range_index/_doc/2 { "ip_allowlist" : "192.168.0.0/16" }
Parameters for range fields
editThe following parameters are accepted by range types:
Try to convert strings to numbers and truncate fractions for integers.
Accepts |
|
Should the field be stored on disk in a column-stride fashion, so that it
can later be used for sorting, aggregations, or scripting? Accepts |
|
Should the field be searchable? Accepts |
|
Whether the field value should be stored and retrievable separately from
the |
Synthetic _source
editSynthetic _source
is Generally Available only for TSDB indices
(indices that have index.mode
set to time_series
). For other indices
synthetic _source
is in technical preview. Features in technical preview may
be changed or removed in a future release. Elastic will work to fix
any issues, but features in technical preview are not subject to the support SLA
of official GA features.
range
fields support synthetic _source
in their default
configuration.
Synthetic source may sort range
field values and remove duplicates for all range
fields except ip_range
. Ranges are sorted by their lower bound and then by upper bound. For example:
const response = await client.indices.create({ index: "idx", settings: { index: { mapping: { source: { mode: "synthetic", }, }, }, }, mappings: { properties: { my_range: { type: "long_range", }, }, }, }); console.log(response); const response1 = await client.index({ index: "idx", id: 1, document: { my_range: [ { gte: 200, lte: 300, }, { gte: 1, lte: 100, }, { gte: 200, lte: 300, }, { gte: 200, lte: 500, }, ], }, }); console.log(response1);
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "long_range" } } } } PUT idx/_doc/1 { "my_range": [ { "gte": 200, "lte": 300 }, { "gte": 1, "lte": 100 }, { "gte": 200, "lte": 300 }, { "gte": 200, "lte": 500 } ] }
Will become:
{ "my_range": [ { "gte": 1, "lte": 100 }, { "gte": 200, "lte": 300 }, { "gte": 200, "lte": 500 } ] }
Values of ip_range
fields are not sorted but original order is not preserved. Duplicate ranges are removed. If ip_range
field value is provided as a CIDR, it will be represented as a range of IP addresses in synthetic source.
For example:
const response = await client.indices.create({ index: "idx", settings: { index: { mapping: { source: { mode: "synthetic", }, }, }, }, mappings: { properties: { my_range: { type: "ip_range", }, }, }, }); console.log(response); const response1 = await client.index({ index: "idx", id: 1, document: { my_range: [ "10.0.0.0/24", { gte: "10.0.0.0", lte: "10.0.0.255", }, ], }, }); console.log(response1);
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "ip_range" } } } } PUT idx/_doc/1 { "my_range": [ "10.0.0.0/24", { "gte": "10.0.0.0", "lte": "10.0.0.255" } ] }
Will become:
{ "my_range": { "gte": "10.0.0.0", "lte": "10.0.0.255" } }
Range field values are always represented as inclusive on both sides with bounds adjusted accordingly. Default values for range bounds are represented as null
. This is true even if range bound was explicitly provided. For example:
const response = await client.indices.create({ index: "idx", settings: { index: { mapping: { source: { mode: "synthetic", }, }, }, }, mappings: { properties: { my_range: { type: "long_range", }, }, }, }); console.log(response); const response1 = await client.index({ index: "idx", id: 1, document: { my_range: { gt: 200, lt: 300, }, }, }); console.log(response1);
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "long_range" } } } } PUT idx/_doc/1 { "my_range": { "gt": 200, "lt": 300 } }
Will become:
{ "my_range": { "gte": 201, "lte": 299 } }
Default values for range bounds are represented as null
in synthetic source. This is true even if range bound was explicitly provided with default value. For example:
const response = await client.indices.create({ index: "idx", settings: { index: { mapping: { source: { mode: "synthetic", }, }, }, }, mappings: { properties: { my_range: { type: "integer_range", }, }, }, }); console.log(response); const response1 = await client.index({ index: "idx", id: 1, document: { my_range: { lte: 2147483647, }, }, }); console.log(response1);
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "integer_range" } } } } PUT idx/_doc/1 { "my_range": { "lte": 2147483647 } }
Will become:
{ "my_range": { "gte": null, "lte": null } }
date
ranges are formatted using provided format
or by default using yyyy-MM-dd'T'HH:mm:ss.SSSZ
format. For example:
const response = await client.indices.create({ index: "idx", settings: { index: { mapping: { source: { mode: "synthetic", }, }, }, }, mappings: { properties: { my_range: { type: "date_range", }, }, }, }); console.log(response); const response1 = await client.index({ index: "idx", id: 1, document: { my_range: [ { gte: 1504224000000, lte: 1504569600000, }, { gte: "2017-09-01", lte: "2017-09-10", }, ], }, }); console.log(response1);
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "date_range" } } } } PUT idx/_doc/1 { "my_range": [ { "gte": 1504224000000, "lte": 1504569600000 }, { "gte": "2017-09-01", "lte": "2017-09-10" } ] }
Will become:
{ "my_range": [ { "gte": "2017-09-01T00:00:00.000Z", "lte": "2017-09-05T00:00:00.000Z" }, { "gte": "2017-09-01T00:00:00.000Z", "lte": "2017-09-10T23:59:59.999Z" } ] }