# A watch Alert on an Aggregation's Aggregation AKA an array of arrays

**URL:** <https://discuss.elastic.co/t/a-watch-alert-on-an-aggregations-aggregation-aka-an-array-of-arrays/113840>\
**Category:** Elasticsearch\
**Created:** [January 2, 2018, 9:30pm UTC](https://discuss.elastic.co/t/a-watch-alert-on-an-aggregations-aggregation-aka-an-array-of-arrays/113840 "2018-01-02T21:30:19Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![megadevx](https://avatars.discourse-cdn.com/v4/letter/m/c67d28/32.png) [@megadevx](https://discuss.elastic.co/u/megadevx)\
**Post date:** [January 2, 2018, 9:30pm UTC](https://discuss.elastic.co/t/a-watch-alert-on-an-aggregations-aggregation-aka-an-array-of-arrays/113840/1 "2018-01-02T21:30:19Z")

</div>

I need help creating the correct compare to trigger with watch.  
The bolded doc count is what I need to trigger the watch however it appears multiple times.

I am trying to create a watch on count of dst\_ip by each client\_ip. Thus I need the watch to compare to compare the whole array of client\_ip's and then each of the sub arrays of each dst\_ip count for each of the client ips.  
This is the aggregation I use on firewall logs:

> ```
> {
> "size": 0,
> "aggs": {
> "last_15m": {
> "range": {
> "field": "@timestamp",
> "ranges": [
> {
> "from": "now-15m",
> "to": "now"
> }
> ]
> },
> "aggs": {
> "denied": {
> "filter": {
> "term": {
> "action": "denied"
> }
> },
> "aggs": {
> "client_ips": {
> "terms": {
> "field": "client_ip",
> "size": 10
> },
> "aggs": {
> "dst_ip_per_client": {
> "terms": {
> "field": "dst_ip",
> "size": 10
> }
> }
> }
> }
> }
> }
> }
> }
> }
> },
> "indices": [
> "cisco-asa*"
> ]
> }
> }
> },
> 
> ```

The aggregation I use gets info back with the following: (I replaced the client\_ip and dst\_ip with \client\_ip\ \dst\_ip\)

> {  
> "ctx" : {  
> "metadata" : null,  
> "watch\_id" : "_inlined_",  
> "payload" : {  
> "\_shards" : {  
> "total" : 146,  
> "failed" : 0,  
> "successful" : 146  
> },  
> "hits" : {  
> "hits" : ,  
> "total" : 937275493,  
> "max\_score" : 0.0  
> },  
> "took" : 3551,  
> "timed\_out" : false,  
> "aggregations" : {  
> "last\_15m" : {  
> "buckets" : [  
> {  
> "from\_as\_string" : "2018-01-02T20:53:41.512Z",  
> "doc\_count" : 34862,  
> "to\_as\_string" : "2018-01-02T21:08:41.512Z",  
> "from" : 1.514926421512E12,  
> "to" : 1.514927321512E12,  
> "denied" : {  
> "doc\_count" : 3788,  
> "client\_ips" : {  
> "doc\_count\_error\_upper\_bound" : 40,  
> "sum\_other\_doc\_count" : 2078,  
> "buckets" : [  
> {  
> "doc\_count" : 304,  
> "dst\_ip\_per\_client" : {  
> "doc\_count\_error\_upper\_bound" : 1,  
> "sum\_other\_doc\_count" : 126,  
> "buckets" : [  
> {  
> **"doc\_count" : 48,**  
> "key": \dst\_ip\  
> }  
> ]  
> "key": \Client\_ip\  
> }  
> goes on some more with more buckets for each client\_ip and then an array with the top ten dst\_ip's on \>that ip......

Any help that could be given would be great!

---

<div class="post-metadata">

**Author:** ![megadevx](https://avatars.discourse-cdn.com/v4/letter/m/c67d28/32.png) [@megadevx](https://discuss.elastic.co/u/megadevx)\
**Post date:** [January 2, 2018, 9:42pm UTC](https://discuss.elastic.co/t/a-watch-alert-on-an-aggregations-aggregation-aka-an-array-of-arrays/113840/2 "2018-01-02T21:42:01Z")

</div>

Would using the script condition be the way to do it?  
Can I do a loop and then another loop to go through each of the buckets?  
like:

> for each client ip {  
> for each dst\_ip{  
> if the doc count \> 10{  
> trigger;  
> } } }

---

<div class="post-metadata">

**Author:** ![spinscale](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/spinscale/32/25011_2.png) [@spinscale](https://discuss.elastic.co/u/spinscale)\
**Post date:** [January 3, 2018, 9:40am UTC](https://discuss.elastic.co/t/a-watch-alert-on-an-aggregations-aggregation-aka-an-array-of-arrays/113840/3 "2018-01-03T09:40:54Z")

</div>

hey,

you can use the `min_doc_count` in the `terms` aggregation, so you only need to check for the bucket size.

Also, you should move the time range and term filter into the query part.

The condition now basically boils down to check the size of the first bucket like this

```auto
return ctx.payload.aggregations.client_ips.buckets.size() > 0 && ctx.payload.aggregations.client_ips.buckets[0].dst_ip.buckets.size() > 0

```

The above one is untested, but should give you an idea.

Also, please properly format your snippets, the above is super hard to read. Alternatively just use a gist.

Thanks!

--Alex

---

<div class="post-metadata">

**Author:** ![megadevx](https://avatars.discourse-cdn.com/v4/letter/m/c67d28/32.png) [@megadevx](https://discuss.elastic.co/u/megadevx)\
**Post date:** [January 3, 2018, 2:19pm UTC](https://discuss.elastic.co/t/a-watch-alert-on-an-aggregations-aggregation-aka-an-array-of-arrays/113840/4 "2018-01-03T14:19:49Z")

</div>

Thank you! I will try this out and will attempt to reformat my snippets to be more human readable.

---

<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:** [January 31, 2018, 2:20pm UTC](https://discuss.elastic.co/t/a-watch-alert-on-an-aggregations-aggregation-aka-an-array-of-arrays/113840/5 "2018-01-31T14:20:18Z")

</div>

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