# Iterate through influencer\_field\_values when they contain more than one value, that exists inside ctx.payload.hits.hits.stream()

**URL:** <https://discuss.elastic.co/t/iterate-through-influencer-field-values-when-they-contain-more-than-one-value-that-exists-inside-ctx-payload-hits-hits-stream/253156>\
**Category:** Kibana\
**Tags:** elastic-stack-monitoring, elastic-stack-machine-learning, elastic-stack-alerting, painless\
**Created:** [October 23, 2020, 3:22pm UTC](https://discuss.elastic.co/t/iterate-through-influencer-field-values-when-they-contain-more-than-one-value-that-exists-inside-ctx-payload-hits-hits-stream/253156 "2020-10-23T15:22:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ironcard](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ironcard/32/77793_2.png) [@ironcard](https://discuss.elastic.co/u/ironcard)\
**Post date:** [October 23, 2020, 3:22pm UTC](https://discuss.elastic.co/t/iterate-through-influencer-field-values-when-they-contain-more-than-one-value-that-exists-inside-ctx-payload-hits-hits-stream/253156/1 "2020-10-23T15:22:24Z")

</div>

Consider the following output:

```
Anomaly on Sep 16 @ 11:45 PM:
Partner: p1 Brand: b1
Score=94.71 Actual=15 Typical=744.49

```

How do I go about adding more partners or brands, instead of getting this:

```
Anomaly on Sep 16 @ 11:45 PM:
Partner: {0=p1, 1=p2} Brand: {0=b1, 1=b2}
Score=94.71 Actual=15 Typical=744.49

```

And End up with this:

```
== Anomaly on Sep 16 @ 11:45 PM: ==
Partner: p1, p2 Brand: b1, b2
Score=94.71 Actual=15 Typical=744.49

```

I can get the following:

partner=  
`p._source.influencers[0]['influencer_field_values'].0`

or

brand=  
`p._source.influencers[1]['influencer_field_values'].0`

if I actually specify it, but not all have more than 1, so how do I loop:

`p._source.influencers[..]['influencer_field_values']`

to display either:  
`[..]['influencer_field_values'].0`  
`[..]['influencer_field_values'].1`  
`[..]['influencer_field_values'].2`  
?

( where .. is either [0] or [1] depending on if I am trying to get partner or brand. The end (.0 or .1 or .2 ) is the part Im trying to figure out how to iterate.

Here is what I have to transform the output I have now:

```
  "transform": {
    "script": {
      "source": "def df = new DecimalFormat('##.##'); return ['anomaly_details':ctx.payload.hits.hits.stream().map(p -> ['start_time':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).minus(Duration.ofMinutes(20)).format(DateTimeFormatter.ofPattern('MMM d @ h:mm a')),'end_time':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).plus(Duration.ofMinutes(20)).format(DateTimeFormatter.ofPattern('MMM d @ h:mm a')),'bucket_time':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern('MMM d @ h:mm a')),'job_id':p._source.job_id,'score':df.format(p._source.record_score),'actual':df.format(p._source.actual.0),'typical':df.format(p._source.typical.0),'partner':p._source.influencers[0]['influencer_field_values'].0,'brand':p._source.influencers[1]['influencer_field_values'].0,'start_time_iso_instant':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).minus(Duration.ofMinutes(20)).format(DateTimeFormatter.ISO_INSTANT),'end_time_iso_instant':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).plus(Duration.ofMinutes(20)).format(DateTimeFormatter.ISO_INSTANT) ]).collect(Collectors.toList())]",
      "lang": "painless"
    }
```

---

<div class="post-metadata">

**Author:** ![richcollier](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/richcollier/32/115035_2.png) [@richcollier](https://discuss.elastic.co/u/richcollier)\
**Post date:** [October 23, 2020, 8:03pm UTC](https://discuss.elastic.co/t/iterate-through-influencer-field-values-when-they-contain-more-than-one-value-that-exists-inside-ctx-payload-hits-hits-stream/253156/2 "2020-10-23T20:03:26Z")

</div>

See example here: [https://gist.github.com/richcollier/1c2b8161286bdca6c553859f28d3d66d](https://gist.github.com/richcollier/1c2b8161286bdca6c553859f28d3d66d)

```auto
    "actions": {
      "log": {
        "transform": {
          "script": """
          return ctx.payload.hits.hits.stream()
          .map(p -> [
            'airline':p.fields.split.0,
            'score':p.fields.score.0,
            'actual':p.fields.actual.0,
            'typical':p.fields.typical.0,
            'timestamp':p.fields.timestamp_iso8601.0,
            'start':p.fields.start.0,
            'end':p.fields.end.0
            ])
            .collect(Collectors.toList());
"""
        },
        "logging": {
          "text": """
Anomalies:
==========
{{#ctx.payload._value}}
time={{timestamp}} 
airline={{airline}} 
score={{score}} (out of 100) 
responsetime={{actual}}ms (typical={{typical}}ms)
link= http://localhost:5601/app/ml#/timeseriesexplorer/?_g=(ml:(jobIds:!({{ctx.metadata.job_id}})),refreshInterval:(display:Off,pause:!f,value:0),time:(from:'{{start}}',mode:absolute,to:'{{end}}'))&_a=(filters:!(),mlSelectInterval:(interval:(display:Auto,val:auto)),mlSelectSeverity:(threshold:(display:warning,val:0)),mlTimeSeriesExplorer:(detectorIndex:0,entities:(airline:{{airline}})),query:(query_string:(analyze_wildcard:!t,query:'*')))
{{/ctx.payload._value}}
"""
        }
      }
    }
  }

```

You use "mustache" syntax to iterate through the results with the `{{#name}}` to start the loop and `{{/name}}` to end the loop definition

---

<div class="post-metadata">

**Author:** ![ironcard](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ironcard/32/77793_2.png) [@ironcard](https://discuss.elastic.co/u/ironcard)\
**Post date:** [October 24, 2020, 12:33am UTC](https://discuss.elastic.co/t/iterate-through-influencer-field-values-when-they-contain-more-than-one-value-that-exists-inside-ctx-payload-hits-hits-stream/253156/3 "2020-10-24T00:33:43Z")

</div>

@richcollier, I tried with that, so let me show you more of my data. Its like I need mustache inside of mustache. ( Where I list brand.0 and partner.0 , I would like to know how many brands or partners there are, since this IS for one record.)

so, sometimes _Brand_={{brand.0}}  
or  
_Brand_={{brand.0}} {{brand.1}}

```
  "attachments": [
    {
      "color": "danger",
      "title": ":rotating_light: Alert - Anomalies:",
      "text": """{{#ctx.payload.anomaly_details}} == *Anomaly on {{bucket_time}}:* ==
*Partner*={{partner.0}} *Brand*={{brand.0}}
*Score*={{score}} *Actual*={{actual}} *Typical*={{typical}}
< Dashboard Link >

      {{/ctx.payload.anomaly_details}}
       """

```

If I change my transform to this:

```
"transform": {
    "script": {
      "source": "def df = new DecimalFormat('##.##'); return ['anomaly_details':ctx.payload.hits.hits.stream().map(p -> ['start_time':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).minus(Duration.ofMinutes(20)).format(DateTimeFormatter.ofPattern('MMM d @ h:mm a')),'end_time':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).plus(Duration.ofMinutes(20)).format(DateTimeFormatter.ofPattern('MMM d @ h:mm a')),'bucket_time':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern('MMM d @ h:mm a')),'job_id':p._source.job_id,'score':df.format(p._source.record_score),'actual':df.format(p._source.actual.0),'typical':df.format(p._source.typical.0),'partner':p._source.influencers[0]['influencer_field_values'],'brand':p._source.influencers[1]['influencer_field_values'],'start_time_iso_instant':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).minus(Duration.ofMinutes(20)).format(DateTimeFormatter.ISO_INSTANT),'end_time_iso_instant':Instant.ofEpochMilli(p._source.timestamp).atZone(ZoneId.systemDefault()).plus(Duration.ofMinutes(20)).format(DateTimeFormatter.ISO_INSTANT) ]).collect(Collectors.toList())]",
      "lang": "painless"
    }

```

In the above transform, the part Im talking about is:

`'partner':p._source.influencers[0]['influencer_field_values'],'brand':p._source.influencers[1]['influencer_field_values']`

As you can see I am using mustache already and the partner and brand are already inside the {{#ctx.payload.anomaly\_details}}, but sometimes the partner or brand value can contain more than one value for the same doc. So how do I loop again inside them while inside the {{/ctx.payload.anomaly\_details}} ?

---

<div class="post-metadata">

**Author:** ![richcollier](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/richcollier/32/115035_2.png) [@richcollier](https://discuss.elastic.co/u/richcollier)\
**Post date:** [October 26, 2020, 6:13pm UTC](https://discuss.elastic.co/t/iterate-through-influencer-field-values-when-they-contain-more-than-one-value-that-exists-inside-ctx-payload-hits-hits-stream/253156/4 "2020-10-26T18:13:54Z")

</div>

Turns out, you can nest mustache.

Step 1: in your transform script, add the whole `influencer_field_values` objects to the map:

```auto
'partner':p._source.influencers[0]['influencer_field_values'],
'brand':p._source.influencers[1]['influencer_field_values']

```

Step 2: make your mustache nested

```auto
{{#ctx.payload.anomaly_details}}
== *Anomaly on {{bucket_time}}:* ==
*Partner*={{#partner}}{{.}} {{/partner}} *Brand*={{#brand}}{{.}} {{/brand}}
*Score*={{score}} *Actual*={{actual}} *Typical*={{typical}}
{{/ctx.payload.anomaly_details}}

```

Then the result would look something like:

```auto
== *Anomaly on Feb 1 @ 11:06 AM:* ==
*Partner*=p3 p4 *Brand*=b3 b4 
*Score*=14.24 *Actual*=17 *Typical*=1.71
== *Anomaly on Feb 1 @ 10:00 AM:* ==
*Partner*=p1 p2 *Brand*=b1 b2 
*Score*=3.19 *Actual*=17 *Typical*=1.71

```

---

<div class="post-metadata">

**Author:** ![ironcard](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ironcard/32/77793_2.png) [@ironcard](https://discuss.elastic.co/u/ironcard)\
**Post date:** [October 26, 2020, 6:20pm UTC](https://discuss.elastic.co/t/iterate-through-influencer-field-values-when-they-contain-more-than-one-value-that-exists-inside-ctx-payload-hits-hits-stream/253156/5 "2020-10-26T18:20:42Z")

</div>

@richcollier, Thank you so Much!! That worked perfectly!

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [November 23, 2020, 6:20pm UTC](https://discuss.elastic.co/t/iterate-through-influencer-field-values-when-they-contain-more-than-one-value-that-exists-inside-ctx-payload-hits-hits-stream/253156/6 "2020-11-23T18:20:43Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
