2016-06-28 3 views
6

Я использую Elasticsearch 2.3, и я пытаюсь выполнить двухэтапное вычисление с использованием агрегации конвейера. Меня интересует конечный результат агрегации конвейера, но Elasticsearch возвращает всю информацию о ведрах.Как выполнить агрегацию конвейера, не возвращая все ведра в Elasticsearch

Поскольку у меня огромное количество ведер (десятки или сотни миллионов), это непомерно. К сожалению, я не могу найти способ сказать Es не возвращать всю эту информацию.

Вот пример игрушки. У меня есть индекс test-index с типом документа obj. obj имеет два поля: key и values.

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 100, 
    "key": "foo" 
}' 

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 20, 
    "key": "foo" 
}' 

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 50, 
    "key": "bar" 
}' 

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 60, 
    "key": "bar" 
}' 

curl -XPOST 'http://10.10.0.7:9200/test-index/obj' -d '{ 
    "value": 70, 
    "key": "bar" 
}' 

Я хочу, чтобы получить среднее значение (по всем key ы) минимальных value в obj с, имеющих одинаковые key с. Среднее значение минимумов.

Elasticsearch позволяет мне это сделать:

curl -XPOST 'http://10.10.0.7:9200/test-index/obj/_search' -d '{ 
    "size": 0, 
    "query": { 
    "match_all": {} 
    }, 
    "aggregations": { 
    "key_aggregates": { 
     "terms": { 
     "field": "key", 
     "size": 0 
     }, 
     "aggs": { 
     "min_value": { 
      "min": { 
      "field": "value" 
      } 
     } 
     } 
    }, 
    "avg_min_value": { 
     "avg_bucket": { 
     "buckets_path": "key_aggregates>min_value" 
     } 
    } 
    } 
}' 

Но этот запрос возвращает минимальное значение для каждого ведра, хотя я и не нужен:

{ 
    "took": 21, 
    "timed_out": false, 
    "_shards": { 
    "total": 5, 
    "successful": 5, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 4, 
    "max_score": 0, 
    "hits": [ 

    ] 
    }, 
    "aggregations": { 
    "key_aggregates": { 
     "doc_count_error_upper_bound": 0, 
     "sum_other_doc_count": 0, 
     "buckets": [ 
     { 
      "key": "bar", 
      "doc_count": 2, 
      "min_value": { 
      "value": 50 
      } 
     }, 
     { 
      "key": "foo", 
      "doc_count": 2, 
      "min_value": { 
      "value": 20 
      } 
     } 
     ] 
    }, 
    "avg_min_value": { 
     "value": 35 
    } 
    } 
} 

Есть ли способ, чтобы избавиться от всей информации внутри "buckets": [...]? Меня интересует только avg_min_value.

Это может не показаться проблемой в этом примере игрушек, но когда число разных key s не велико (десятки или сотни миллионов), ответ запроса является чрезмерно большим, и я бы хотел его обрезать.

Есть ли способ сделать это с помощью Elasticsearch? Или я неправильно моделирую свои данные?

NB: недопустимо предварительно агрегировать данные на ключ, поскольку часть моего запроса может быть заменена сложными и неизвестными фильтрами.

NB2: изменение size на неотрицательное число в моем terms агрегации неприемлемо, потому что это изменит результат.

ответ

5

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

Вы можете использовать функцию Response Filtering, чтобы отфильтровать часть ответа, которую вы хотите получить.

Вы должны быть в состоянии добиться того, чего хотите, добавив параметр запроса filter_path=aggregations.avg_min_value к URL-адресу поиска. В случае примера, он должен выглядеть примерно так:

curl -XPOST 'http://10.10.0.7:9200/test-index/obj/_search?filter_path=aggregations.avg_min_value' -d '{ 
    "size": 0, 
    "query": { 
    "match_all": {} 
    }, 
    "aggregations": { 
    "key_aggregates": { 
     "terms": { 
     "field": "key", 
     "size": 0 
     }, 
     "aggs": { 
     "min_value": { 
      "min": { 
      "field": "value" 
      } 
     } 
     } 
    }, 
    "avg_min_value": { 
     "avg_bucket": { 
     "buckets_path": "key_aggregates>min_value" 
     } 
    } 
    } 
}' 

PS: если вы нашли другое решение, не могли бы вы поделиться его здесь? Благодаря!

+1

Это кажется идеальным решением. Если бы мы это нашли! Мы не нашли прямого решения этой проблемы, поэтому мы приняли способ агрегации сценариев: построение карты, ключи которой являются полем «ключ», и значения минимумов по всем документам с заданным значением для «ключа» поля; затем агрегирование значений этой карты.Я не знаю, как они сравниваются с точки зрения производительности, но, по всей вероятности, ваше решение должно быть быстрее! – jrjd

Смежные вопросы