2014-05-15 06:36:05 -04:00
|
|
|
[[java-aggs-metrics-scripted-metric]]
|
|
|
|
==== Scripted Metric Aggregation
|
|
|
|
|
|
|
|
Here is how you can use
|
|
|
|
{ref}/search-aggregations-metrics-scripted-metric-aggregation.html[Scripted Metric Aggregation]
|
|
|
|
with Java API.
|
|
|
|
|
|
|
|
Don't forget to add Groovy in your classpath if you want to run Groovy scripts in an embedded data node
|
|
|
|
(for unit tests for example).
|
|
|
|
For example, with Maven, add this dependency to your `pom.xml` file:
|
|
|
|
|
|
|
|
[source,xml]
|
|
|
|
--------------------------------------------------
|
|
|
|
<dependency>
|
|
|
|
<groupId>org.codehaus.groovy</groupId>
|
|
|
|
<artifactId>groovy-all</artifactId>
|
|
|
|
<version>2.3.2</version>
|
|
|
|
<classifier>indy</classifier>
|
|
|
|
</dependency>
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
===== Prepare aggregation request
|
|
|
|
|
|
|
|
Here is an example on how to create the aggregation request:
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
MetricsAggregationBuilder aggregation =
|
|
|
|
AggregationBuilders
|
|
|
|
.scriptedMetric("agg")
|
|
|
|
.initScript("_agg['heights'] = []")
|
2015-05-12 05:37:22 -04:00
|
|
|
.mapScript(new Script("if (doc['gender'].value == \"male\") " +
|
2014-05-15 06:36:05 -04:00
|
|
|
"{ _agg.heights.add(doc['height'].value) } " +
|
|
|
|
"else " +
|
2015-05-12 05:37:22 -04:00
|
|
|
"{ _agg.heights.add(-1 * doc['height'].value) }"));
|
2014-05-15 06:36:05 -04:00
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
You can also specify a `combine` script which will be executed on each shard:
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
MetricsAggregationBuilder aggregation =
|
|
|
|
AggregationBuilders
|
|
|
|
.scriptedMetric("agg")
|
2015-05-12 05:37:22 -04:00
|
|
|
.initScript(new Script("_agg['heights'] = []"))
|
|
|
|
.mapScript(new Script("if (doc['gender'].value == \"male\") " +
|
2014-05-15 06:36:05 -04:00
|
|
|
"{ _agg.heights.add(doc['height'].value) } " +
|
|
|
|
"else " +
|
2015-05-12 05:37:22 -04:00
|
|
|
"{ _agg.heights.add(-1 * doc['height'].value) }"))
|
|
|
|
.combineScript(new Script("heights_sum = 0; for (t in _agg.heights) { heights_sum += t }; return heights_sum"));
|
2014-05-15 06:36:05 -04:00
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
You can also specify a `reduce` script which will be executed on the node which gets the request:
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
MetricsAggregationBuilder aggregation =
|
|
|
|
AggregationBuilders
|
|
|
|
.scriptedMetric("agg")
|
2015-05-12 05:37:22 -04:00
|
|
|
.initScript(new Script("_agg['heights'] = []"))
|
|
|
|
.mapScript(new Script("if (doc['gender'].value == \"male\") " +
|
2014-05-15 06:36:05 -04:00
|
|
|
"{ _agg.heights.add(doc['height'].value) } " +
|
|
|
|
"else " +
|
2015-05-12 05:37:22 -04:00
|
|
|
"{ _agg.heights.add(-1 * doc['height'].value) }"))
|
|
|
|
.combineScript(new Script("heights_sum = 0; for (t in _agg.heights) { heights_sum += t }; return heights_sum"))
|
|
|
|
.reduceScript(new Script("heights_sum = 0; for (a in _aggs) { heights_sum += a }; return heights_sum"));
|
2014-05-15 06:36:05 -04:00
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
===== Use aggregation response
|
|
|
|
|
|
|
|
Import Aggregation definition classes:
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
|
|
|
|
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
[source,java]
|
|
|
|
--------------------------------------------------
|
|
|
|
// sr is here your SearchResponse object
|
|
|
|
ScriptedMetric agg = sr.getAggregations().get("agg");
|
|
|
|
Object scriptedResult = agg.aggregation();
|
|
|
|
logger.info("scriptedResult [{}]", scriptedResult);
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
Note that the result depends on the script you built.
|
|
|
|
For the first example, this will basically produce:
|
|
|
|
|
|
|
|
[source,text]
|
|
|
|
--------------------------------------------------
|
|
|
|
scriptedResult object [ArrayList]
|
|
|
|
scriptedResult [ {
|
|
|
|
"heights" : [ 1.122218480146643, -1.8148918111233887, -1.7626731575142909, ... ]
|
|
|
|
}, {
|
|
|
|
"heights" : [ -0.8046067304119863, -2.0785486707864553, -1.9183567430207953, ... ]
|
|
|
|
}, {
|
|
|
|
"heights" : [ 2.092635728868694, 1.5697545960886536, 1.8826954461968808, ... ]
|
|
|
|
}, {
|
|
|
|
"heights" : [ -2.1863201099468403, 1.6328549117346856, -1.7078288405893842, ... ]
|
|
|
|
}, {
|
|
|
|
"heights" : [ 1.6043904836424177, -2.0736538674414025, 0.9898266674373053, ... ]
|
|
|
|
} ]
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
The second example will produce:
|
|
|
|
|
|
|
|
[source,text]
|
|
|
|
--------------------------------------------------
|
|
|
|
scriptedResult object [ArrayList]
|
|
|
|
scriptedResult [-41.279615707402876,
|
|
|
|
-60.88007362339038,
|
|
|
|
38.823270659734256,
|
|
|
|
14.840192739445632,
|
|
|
|
11.300902755741326]
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
The last example will produce:
|
|
|
|
|
|
|
|
[source,text]
|
|
|
|
--------------------------------------------------
|
|
|
|
scriptedResult object [Double]
|
|
|
|
scriptedResult [2.171917696507009]
|
|
|
|
--------------------------------------------------
|
|
|
|
|