Вы можете использовать scripted_metric агрегация безболезненным скриптом
Запрос
Я объясню это более подробно ниже.
POST index/type/_search
{
"size": 0,
"aggs": {
"colorgroups": {
"scripted_metric": {
"init_script" : "params._agg.transactions = [:]",
"map_script": "params.key = doc['colorname'].value; if(params._agg.transactions[params.key] == null){ params._agg.transactions[params.key] = 1; }else{ params._agg.transactions[params.key] ++ }",
"combine_script": "return params._agg.transactions;",
"reduce_script": "params.color_counters =[:]; params.groups_counters =[:]; for(shard_result in params._aggs){ for(color_name in shard_result.keySet()){ if(params.color_counters[color_name] == null){ params.color_counters[color_name] = shard_result[color_name] }else{ params.color_counters[color_name] = params.color_counters[color_name] + shard_result[color_name] } } } for(color_name in params.color_counters.keySet()){ params.group_counter = params.color_counters[color_name].toString(); if(params.groups_counters[params.group_counter] == null){ params.groups_counters[params.group_counter] = 1 }else{ params.groups_counters[params.group_counter] ++ } } return params.groups_counters"
}
}
}
}
Результат
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 9,
"max_score": 0,
"hits": []
},
"aggregations": {
"colorgroups": {
"value": {
"2": 3,
"1": 2,
"1": 1
}
}
}
}
init_script
инициализируйте некоторые значения, чтобы сохранить промежуточные результаты
params._agg.transactions = [:]
map_script
Расчеты по каждому документу. Постарайтесь сделать его небольшим и сократите как можно больше данных на этом шаге.
params.key = doc['colorname'].value;
if(params._agg.transactions[params.key] == null){
params._agg.transactions[params.key] = 1;
}else{
params._agg.transactions[params.key] ++
}
комбинированный_скрипт
Расчеты для каждого шарда. Мы уже все сделали в map_script, просто возвращаем hash map
return params._agg.transactions
уменьшить_скрипт
Работа с частичными агрегациями из каждого шарда. Сначала нам нужно объединить их в один HashMap. И сгруппировать по значению счетчика после
params.color_counters =[:];
params.groups_counters =[:];
//merging all partial aggregations to params.color_counters
for(shard_result in params._aggs){
for(color_name in shard_result.keySet()){
if(params.color_counters[color_name] == null){
params.color_counters[color_name] = shard_result[color_name]
}else{
params.color_counters[color_name] = params.color_counters[color_name] + shard_result[color_name]
}
}
}
//Grouping by color counter to params.groups_counters
for(color_name in params.color_counters.keySet()){
params.group_counter = params.color_counters[color_name].toString();
if(params.groups_counters[params.group_counter] == null){
params.groups_counters[params.group_counter] = 1
}else{
params.groups_counters[params.group_counter] ++
}
}
return params.groups_counters
Вы можете позвонить
Debug.explain(variable);
в любом месте безболезненного скрипта для отладки переменной и настройки скрипта под свои нужды.
person
pkhlop
schedule
07.02.2018