blue112
blue112

Reputation: 56412

Count of unique aggregration doc_count in ElasticSearch

Using ElasticSearch 7.0, I can get how many log I have for each user with an aggregation :

"aggs": {
    "by_user": {
        "terms": {
            "field": "user_id",
        }
    }
}

This returns me something like:

user32: 25
user52: 20
user10: 20
...

What I would like is to know how many user have 25 logs, and how many user have 20 logs etc. The ideal result would be something like :

25: 1
20: 2
19: 4
12: 54

Because 54 users have 12 logs lines.

How can I make an aggregation that returns this result ?

Upvotes: 1

Views: 178

Answers (1)

Andrey Borisko
Andrey Borisko

Reputation: 4609

It sounds like you can use Bucket Script Aggregation to simplify your query but the problem is that there is still open PR on this topic.

So, for now i think the simplest is to use painless script with Scripted Metric Aggregation. I recommend you to carefully read about the stages of its execution.

In terms of code I know it's not the best algorithm for your problem but quick and dirty your query could look something like this:

GET my_index/_search
{
  "size": 0, 
    "query" : {
        "match_all" : {}
    },
    "aggs": {
        "profit": {
            "scripted_metric": {
                "init_script" : "state.transactions = [:];", 
                "map_script" :
                """
                def key = doc['firstName.keyword'];
                if (key != null && key.value != null) {
                  def value = state.transactions[key.value];
                  if(value==null) value = 0;
                  state.transactions[key.value] = value+1
                }
                """,
                "combine_script" : "return state.transactions",
                "reduce_script" : 
                """
                def result = [:];
                for (state in states) {
                  for (item in state.entrySet()) {
                    def key=item.getValue().toString();
                    def value = result[key];
                    if(value==null)value = 0;
                    result[key]=value+1;
                  }
                } 
                return result;
                """
            }
        }
    }
}

Upvotes: 2

Related Questions