mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-29 09:54:06 -04:00
This replaces the `script` docs for bucket aggregations with runtime
fields. We expect runtime fields to be nicer to work with because you
can also fetch them or filter on them. We expect them to be faster
because their don't need this sort of `instanceof` tree:
a92a647b9f/server/src/main/java/org/elasticsearch/search/aggregations/support/values/ScriptDoubleValues.java (L42)
Relates to #69291
Co-authored-by: Adam Locke <adam.locke@elastic.co>
326 lines
6.9 KiB
Text
326 lines
6.9 KiB
Text
[[search-aggregations-bucket-range-aggregation]]
|
|
=== Range aggregation
|
|
++++
|
|
<titleabbrev>Range</titleabbrev>
|
|
++++
|
|
|
|
A multi-bucket value source based aggregation that enables the user to define a set of ranges - each representing a bucket. During the aggregation process, the values extracted from each document will be checked against each bucket range and "bucket" the relevant/matching document.
|
|
Note that this aggregation includes the `from` value and excludes the `to` value for each range.
|
|
|
|
Example:
|
|
|
|
[source,console,id=range-aggregation-example]
|
|
--------------------------------------------------
|
|
GET /_search
|
|
{
|
|
"aggs": {
|
|
"price_ranges": {
|
|
"range": {
|
|
"field": "price",
|
|
"ranges": [
|
|
{ "to": 100.0 },
|
|
{ "from": 100.0, "to": 200.0 },
|
|
{ "from": 200.0 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TEST[setup:sales]
|
|
// TEST[s/GET \/_search/GET \/_search\?filter_path=aggregations/]
|
|
|
|
Response:
|
|
|
|
[source,console-result]
|
|
--------------------------------------------------
|
|
{
|
|
...
|
|
"aggregations": {
|
|
"price_ranges": {
|
|
"buckets": [
|
|
{
|
|
"key": "*-100.0",
|
|
"to": 100.0,
|
|
"doc_count": 2
|
|
},
|
|
{
|
|
"key": "100.0-200.0",
|
|
"from": 100.0,
|
|
"to": 200.0,
|
|
"doc_count": 2
|
|
},
|
|
{
|
|
"key": "200.0-*",
|
|
"from": 200.0,
|
|
"doc_count": 3
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TESTRESPONSE[s/\.\.\.//]
|
|
|
|
==== Keyed Response
|
|
|
|
Setting the `keyed` flag to `true` will associate a unique string key with each bucket and return the ranges as a hash rather than an array:
|
|
|
|
[source,console,id=range-aggregation-keyed-example]
|
|
--------------------------------------------------
|
|
GET /_search
|
|
{
|
|
"aggs": {
|
|
"price_ranges": {
|
|
"range": {
|
|
"field": "price",
|
|
"keyed": true,
|
|
"ranges": [
|
|
{ "to": 100 },
|
|
{ "from": 100, "to": 200 },
|
|
{ "from": 200 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TEST[setup:sales]
|
|
// TEST[s/GET \/_search/GET \/_search\?filter_path=aggregations/]
|
|
|
|
Response:
|
|
|
|
[source,console-result]
|
|
--------------------------------------------------
|
|
{
|
|
...
|
|
"aggregations": {
|
|
"price_ranges": {
|
|
"buckets": {
|
|
"*-100.0": {
|
|
"to": 100.0,
|
|
"doc_count": 2
|
|
},
|
|
"100.0-200.0": {
|
|
"from": 100.0,
|
|
"to": 200.0,
|
|
"doc_count": 2
|
|
},
|
|
"200.0-*": {
|
|
"from": 200.0,
|
|
"doc_count": 3
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TESTRESPONSE[s/\.\.\.//]
|
|
|
|
It is also possible to customize the key for each range:
|
|
|
|
[source,console,id=range-aggregation-custom-keys-example]
|
|
--------------------------------------------------
|
|
GET /_search
|
|
{
|
|
"aggs": {
|
|
"price_ranges": {
|
|
"range": {
|
|
"field": "price",
|
|
"keyed": true,
|
|
"ranges": [
|
|
{ "key": "cheap", "to": 100 },
|
|
{ "key": "average", "from": 100, "to": 200 },
|
|
{ "key": "expensive", "from": 200 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TEST[setup:sales]
|
|
// TEST[s/GET \/_search/GET \/_search\?filter_path=aggregations/]
|
|
|
|
Response:
|
|
|
|
[source,console-result]
|
|
--------------------------------------------------
|
|
{
|
|
...
|
|
"aggregations": {
|
|
"price_ranges": {
|
|
"buckets": {
|
|
"cheap": {
|
|
"to": 100.0,
|
|
"doc_count": 2
|
|
},
|
|
"average": {
|
|
"from": 100.0,
|
|
"to": 200.0,
|
|
"doc_count": 2
|
|
},
|
|
"expensive": {
|
|
"from": 200.0,
|
|
"doc_count": 3
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TESTRESPONSE[s/\.\.\.//]
|
|
|
|
==== Script
|
|
|
|
If the data in your documents doesn't exactly match what you'd like to aggregate,
|
|
use a <<runtime,runtime field>>. For example, if you need to
|
|
apply a particular currency conversion rate:
|
|
|
|
[source,console,id=range-aggregation-runtime-field-example]
|
|
----
|
|
GET /_search
|
|
{
|
|
"runtime_mappings": {
|
|
"price.euros": {
|
|
"type": "double",
|
|
"script": {
|
|
"source": """
|
|
emit(doc['price'].value * params.conversion_rate)
|
|
""",
|
|
"params": {
|
|
"conversion_rate": 0.835526591
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"aggs": {
|
|
"price_ranges": {
|
|
"range": {
|
|
"field": "price.euros",
|
|
"ranges": [
|
|
{ "to": 100 },
|
|
{ "from": 100, "to": 200 },
|
|
{ "from": 200 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
----
|
|
// TEST[setup:sales]
|
|
// TEST[s/GET \/_search/GET \/_search\?filter_path=aggregations/]
|
|
|
|
//////////////////////////
|
|
|
|
[source,console-result]
|
|
----
|
|
{
|
|
"aggregations": {
|
|
"price_ranges": {
|
|
"buckets": [
|
|
{
|
|
"key": "*-100.0",
|
|
"to": 100.0,
|
|
"doc_count": 2
|
|
},
|
|
{
|
|
"key": "100.0-200.0",
|
|
"from": 100.0,
|
|
"to": 200.0,
|
|
"doc_count": 5
|
|
},
|
|
{
|
|
"key": "200.0-*",
|
|
"from": 200.0,
|
|
"doc_count": 0
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
//////////////////////////
|
|
|
|
==== Sub Aggregations
|
|
|
|
The following example, not only "bucket" the documents to the different buckets but also computes statistics over the prices in each price range
|
|
|
|
[source,console,id=range-aggregation-sub-aggregation-example]
|
|
--------------------------------------------------
|
|
GET /_search
|
|
{
|
|
"aggs": {
|
|
"price_ranges": {
|
|
"range": {
|
|
"field": "price",
|
|
"ranges": [
|
|
{ "to": 100 },
|
|
{ "from": 100, "to": 200 },
|
|
{ "from": 200 }
|
|
]
|
|
},
|
|
"aggs": {
|
|
"price_stats": {
|
|
"stats": { "field": "price" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TEST[setup:sales]
|
|
// TEST[s/GET \/_search/GET \/_search\?filter_path=aggregations/]
|
|
|
|
Response:
|
|
|
|
[source,console-result]
|
|
--------------------------------------------------
|
|
{
|
|
...
|
|
"aggregations": {
|
|
"price_ranges": {
|
|
"buckets": [
|
|
{
|
|
"key": "*-100.0",
|
|
"to": 100.0,
|
|
"doc_count": 2,
|
|
"price_stats": {
|
|
"count": 2,
|
|
"min": 10.0,
|
|
"max": 50.0,
|
|
"avg": 30.0,
|
|
"sum": 60.0
|
|
}
|
|
},
|
|
{
|
|
"key": "100.0-200.0",
|
|
"from": 100.0,
|
|
"to": 200.0,
|
|
"doc_count": 2,
|
|
"price_stats": {
|
|
"count": 2,
|
|
"min": 150.0,
|
|
"max": 175.0,
|
|
"avg": 162.5,
|
|
"sum": 325.0
|
|
}
|
|
},
|
|
{
|
|
"key": "200.0-*",
|
|
"from": 200.0,
|
|
"doc_count": 3,
|
|
"price_stats": {
|
|
"count": 3,
|
|
"min": 200.0,
|
|
"max": 200.0,
|
|
"avg": 200.0,
|
|
"sum": 600.0
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TESTRESPONSE[s/\.\.\.//]
|