Подсчет уникальной агрегации doc_count в ElasticSearch - PullRequest
1 голос
/ 22 мая 2019

Используя ElasticSearch 7.0, я могу получить сколько журналов у меня для каждого пользователя с агрегацией:

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

Это возвращает мне что-то вроде:

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

Что бы я хотелэто знать, сколько у пользователя 25 журналов и сколько у пользователя 20 журналов и т. д. Идеальный результат будет выглядеть примерно так:

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

Поскольку у 54 пользователей есть 12 строк журнала.

Как я могу сделать агрегацию, которая возвращает этот результат?

1 Ответ

2 голосов
/ 23 мая 2019

Звучит так, как будто вы можете использовать Bucket Script Aggregation , чтобы упростить ваш запрос, но проблема в том, что все еще открытый PR по этой теме .

Итак,на данный момент я думаю, что самое простое - использовать безболезненный скрипт с Scripted Metric Aggregation .Я рекомендую вам внимательно прочитать этапы его выполнения.

С точки зрения кода, я знаю, что это не лучший алгоритм для вашей проблемы, но быстрый и грязный ваш запрос может выглядеть примерно так:

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;
                """
            }
        }
    }
}
...