<commit_before>[[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.

===== Prepare aggregation request

Here is an example on how to create the aggregation request:

[source,java]
--------------------------------------------------
ScriptedMetricAggregationBuilder aggregation = AggregationBuilders
        .scriptedMetric("agg")
        .initScript(new Script("_agg['heights'] = []"))
        .mapScript(new Script("if (doc['gender'].value == \"male\") " +
                "{ _agg.heights.add(doc['height'].value) } " +
                "else " +
                "{ _agg.heights.add(-1 * doc['height'].value) }"));
--------------------------------------------------

You can also specify a `combine` script which will be executed on each shard:

[source,java]
--------------------------------------------------
ScriptedMetricAggregationBuilder aggregation =
        AggregationBuilders
                .scriptedMetric("agg")
                .initScript(new Script("_agg['heights'] = []"))
                .mapScript(new Script("if (doc['gender'].value == \"male\") " +
                        "{ _agg.heights.add(doc['height'].value) } " +
                        "else " +
                        "{ _agg.heights.add(-1 * doc['height'].value) }"))
                .combineScript(new Script("heights_sum = 0; for (t in _agg.heights) { heights_sum += t }; return heights_sum"));
--------------------------------------------------

You can also specify a `reduce` script which will be executed on the node which gets the request:

[source,java]
--------------------------------------------------
ScriptedMetricAggregationBuilder aggregation =
        AggregationBuilders
                .scriptedMetric("agg")
                .initScript(new Script("_agg['heights'] = []"))
                .mapScript(new Script("if (doc['gender'].value == \"male\") " +
                        "{ _agg.heights.add(doc['height'].value) } " +
                        "else " +
                        "{ _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"));
--------------------------------------------------


===== 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:
<commit_msg>Update script metric aggregation for 5.0<commit_after>[[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.

===== Prepare aggregation request

Here is an example on how to create the aggregation request:

[source,java]
--------------------------------------------------
ScriptedMetricAggregationBuilder aggregation = AggregationBuilders
    .scriptedMetric("agg")
    .initScript(new Script("params._agg.heights = []"))
    .mapScript(new Script("params._agg.heights.add(doc.gender.value == 'male' ? doc.height.value : -1.0 * doc.height.value)"));
--------------------------------------------------

You can also specify a `combine` script which will be executed on each shard:

[source,java]
--------------------------------------------------
ScriptedMetricAggregationBuilder aggregation = AggregationBuilders
    .scriptedMetric("agg")
    .initScript(new Script("params._agg.heights = []"))
    .mapScript(new Script("params._agg.heights.add(doc.gender.value == 'male' ? doc.height.value : -1.0 * doc.height.value)"))
    .combineScript(new Script("double heights_sum = 0.0; for (t in params._agg.heights) { heights_sum += t } return heights_sum"));
--------------------------------------------------

You can also specify a `reduce` script which will be executed on the node which gets the request:

[source,java]
--------------------------------------------------
ScriptedMetricAggregationBuilder aggregation = AggregationBuilders
    .scriptedMetric("agg")
    .initScript(new Script("params._agg.heights = []"))
    .mapScript(new Script("params._agg.heights.add(doc.gender.value == 'male' ? doc.height.value : -1.0 * doc.height.value)"))
    .combineScript(new Script("double heights_sum = 0.0; for (t in params._agg.heights) { heights_sum += t } return heights_sum"))
    .reduceScript(new Script("double heights_sum = 0.0; for (a in params._aggs) { heights_sum += a } return heights_sum"));
--------------------------------------------------


===== 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:

{'fraction_non_alphanumeric': 0.2752836704489393, 'fraction_numerical': 0.00328893274132544, 'mean_word_length': 1.8756501182033096, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5031292', 'n_tokens_mistral': 1568, 'n_tokens_neox': 1486, 'n_words': 372}