2015-10-23 6 views
15

индексированных документов, как:Добавление дополнительных полей для ElasticSearch агрегацию Условия

{ 
    id: 1, 
    title: 'Blah', 
    ... 
    platform: {id: 84, url: 'http://facebook.com', title: 'Facebook'} 
    ... 
} 

То, что я хочу, это счета и вывода статистики по-платформе. Для подсчета, можно использовать агрегацию термины с platform.id в качестве поля для подсчета:

aggs: { 
    platforms: { 
    terms: {field: 'platform.id'} 
    } 
} 

Таким образом, я получаю статистику в качестве нескольких ведер, похожих на {key: 8, doc_count: 162511}, как и ожидалось.

Теперь, могу ли я как-то добавить к этим ковшим также platform.name и platform.url (для получения достаточного результата статистики)? Лучшее, что я пришел с выглядит как:

aggs: { 
    platforms: { 
    terms: {field: 'platform.id'}, 
    aggs: { 
     name: {terms: {field: 'platform.name'}}, 
     url: {terms: {field: 'platform.url'}} 
    } 
    } 
} 

Что, на самом деле, работает, и возвращает довольно сложную структуру в каждом ведре:

{key: 7, 
    doc_count: 528568, 
    url: 
    {doc_count_error_upper_bound: 0, 
    sum_other_doc_count: 0, 
    buckets: [{key: "http://facebook.com", doc_count: 528568}]}, 
    name: 
    {doc_count_error_upper_bound: 0, 
    sum_other_doc_count: 0, 
    buckets: [{key: "Facebook", doc_count: 528568}]}}, 

Конечно, название и URL платформы может быть извлеченный из этой структуры (например, bucket.url.buckets.first.key), но есть ли более чистый и простой способ выполнить эту задачу?

+0

вы нашли какое-либо решение вашей проблемы? Я столкнулся с тем же правом прямо сейчас :( –

+0

Я разместил его ниже как мой собственный «принятый» ответ :) – zverok

ответ

22

Это кажется лучшим способ показать намерения является top hits агрегацией: «от каждой агрегированной группы выбрать только один документ», а затем извлечь из него платформы:

aggs: { 
    platforms: { 
    terms: {field: 'platform.id'}, 
    aggs: { 
     platform: {top_hits: {size: 1, _source: {include: ['platform']}}} 
    } 
} 

T его путь, каждый воспротивился будет выглядеть следующим образом:

{"key": 7, 
    "doc_count": 529939, 
    "platform": { 
    "hits": { 
     "hits": [{ 
     "_source": { 
     "platform": 
      {"id": 7, "name": "Facebook", "url": "http://facebook.com"} 
     } 
     }] 
    } 
    }, 
} 

который является своего рода слишком deeep (как обычно, с ES), но чистый: bucket.platform.hits.hits.first._source.platform

+0

ОК, но это включает все документы в каждом ключе –

0

Если вы не обязательно должны получить значение platform.id, вы могли бы уйти с одним агрегацией используя вместо script, объединяющих два поля name и url:

aggs: { 
    platforms: { 
    terms: {script: 'doc["platform.name"].value + "," + doc["platform.url"].value'} 
    } 
} 
+0

Да, решение с 'script' довольно очевидно. А также довольно уродливый, как и для меня. Просто проверьте, может ли быть что-то более чистое. – zverok

+0

Довольно уверен, что что-то можно сделать с помощью агрегации [scripted metric] (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-scripted-metric-aggregation.html). Я попробую позже, но вы можете сделать это. – Val

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