2015-10-23 1 views
15

documenti indicizzati sono come:L'aggiunta di campi aggiuntivi per elasticsearch termini di aggregazione

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

Quello che voglio è di conteggio e di uscita statistiche-by-piattaforma. Per il conteggio, posso usare termini di aggregazione con platform.id come un campo a contare:

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

In questo modo ho ricevuto le statistiche come un multiplo secchi che assomigliano {key: 8, doc_count: 162511}, come previsto.

Ora, posso in qualche modo aggiungere a quei bucket anche platform.name e platform.url (per un output piuttosto elevato di statistiche)? Il migliore che ho è venuto con un look come:

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

che, di fatto, le opere, e restituisce la struttura piuttosto complicato di ciascun segmento:

{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}]}}, 

Naturalmente, il nome e l'URL della piattaforma potrebbe essere estratto da questa struttura (come bucket.url.buckets.first.key), ma esiste un modo più semplice e pulito per eseguire l'operazione?

+0

Vedi qualche soluzione al vostro problema? Sto affrontando lo stesso adesso :( –

+0

L'ho postato qui sotto come la mia risposta "accettata" :) – zverok

risposta

22

sembra il migliore modo per mostrare intenzioni è top hits aggregazione: "da ciascuno di gruppo aggregato selezionare un solo documento", e quindi estrarre la piattaforma da esso:

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

T la sua strada, ogni sgroppò sarà simile:

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

che è un pò troppo deeep (come al solito con ES), ma pulito: bucket.platform.hits.hits.first._source.platform

+0

ok ma questo include tutti i documenti in ogni chiave –

0

Se non è necessariamente bisogno di ottenere il valore di platform.id, si potrebbe ottenere via con una sola aggregazione utilizzando invece un script che concatena i due campi name e url:

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

Sì, la soluzione con 'script' è abbastanza ovvia. E anche piuttosto brutto, come per me. Sto solo controllando se può esserci qualcosa di più pulito. – zverok

+0

Abbastanza sicuro che si possa fare qualcosa intorno alla metrica [scripted metrica] (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-scripted-metric-aggregation.html). Ci proverò più tardi, ma puoi provarci. – Val