Elasticsearch: aggregazioni a bucket [parte 1]

Con le aggregazioni a bucket di Elasticsearch possiamo creare gruppi di documenti. In questo articolo ci concentreremo principalmente sulle aggregazioni basate sui campi di tipo keyword presenti negli indici. Utilizzeremo diversi esempi per capire le principali differenze tra le funzioni di aggregazione disponibili.

Share

Reading time: 7 minutes

Come introdotto nell’articolo Elasticsearch: le tipologie di aggregazione, Elasticsearch permette non solo di effettuare ricerche sui dati, ma anche di effettuare delle analisi. Tra le varie tipologie viste, in questo articolo ci occuperemo delle aggregazioni a bucket. Queste categorizzano gli insiemi di documenti in gruppi. Il tipo di aggregazione determina se un dato documento rientra o meno in un bucket.

È possibile utilizzare le aggregazioni di bucket per implementare una navigazione sfaccettata (di solito collocata come barra laterale in una pagina di destinazione dei risultati di ricerca), per aiutare gli utenti a restringere i risultati di interesse.

In questo articolo inizieremo ad analizzare alcune aggregazioni appartenenti a questa tipologia. In particolare, ci concentreremo sulle aggregazioni che coinvolgono i termini.

terms

L’aggregazione dei termini crea dinamicamente un bucket per ogni termine univoco di un campo.
L’esempio seguente utilizza l’aggregazione dei termini per trovare il numero di documenti per codice di risposta nei dati di log web:

GET kibana_sample_data_logs/_search
{
  "size": 0,
  "aggs": {
    "response_codes": {
      "terms": {
        "field": "response.keyword",
        "size": 10
      }
    }
  }
} 

Risposta di esempio

...
"aggregations" : {
  "response_codes" : {
    "doc_count_error_upper_bound" : 0,
    "sum_other_doc_count" : 0,
    "buckets" : [
      {
        "key" : "200",
        "doc_count" : 12832
      },
      {
        "key" : "404",
        "doc_count" : 801
      },
      {
        "key" : "503",
        "doc_count" : 441
      }
    ]
  }
 }
} 

I valori sono restituiti con la chiave key. doc_count specifica il numero di documenti in ogni bucket. Per impostazione predefinita, i bucket sono ordinati in ordine decrescente di doc_count.

La risposta include anche due chiavi denominate doc_count_error_upper_bound e sum_other_doc_count.

L’aggregazione dei termini restituisce i termini unici più importanti. Pertanto, se i dati hanno molti termini unici, alcuni di essi potrebbero non comparire nei risultati. Il campo sum_other_doc_count è la somma dei documenti esclusi dalla risposta. In questo caso, il numero è 0 perché tutti i valori univoci appaiono nella risposta.

Il campo doc_count_error_upper_bound rappresenta il massimo conteggio possibile per un valore univoco che viene escluso dai risultati finali. Utilizzare questo campo per stimare il margine di errore del conteggio.

Il conteggio potrebbe non essere accurato. Un nodo di coordinamento responsabile dell’aggregazione chiede a ogni shard i suoi termini unici più importanti. Immaginiamo uno scenario in cui il parametro di dimensione è 3. L’aggregazione dei termini richiede a ogni shard i suoi 3 termini unici principali. Il nodo coordinatore prende tutti i risultati e li aggrega per calcolare il risultato finale. Se uno shard ha un oggetto che non fa parte della top 3, non apparirà nella risposta.

Questo è particolarmente vero se la dimensione è impostata su un numero basso. Poiché la dimensione predefinita è 10, è improbabile che si verifichi un errore. Se non si ha bisogno di un’elevata precisione e si vogliono aumentare le prestazioni, si può ridurre la dimensione.

sampler, diversified_sampler

Se si stanno aggregando milioni di documenti, è possibile utilizzare un’aggregazione di tipo sampler per ridurre la portata a un piccolo campione di documenti e ottenere una risposta più rapida. L’aggregazione sampler seleziona i campioni in base ai documenti con il punteggio più alto.

I risultati sono approssimativi ma rappresentano fedelmente la distribuzione dei dati reali. L’aggregazione sampler migliora significativamente le prestazioni della query, ma le risposte stimate non sono del tutto affidabili.

La sintassi di base è:

“aggs”: {
  "SAMPLE": {
    "sampler": {
      "shard_size": 100
    },
    "aggs": {...}
  }
} 

La proprietà shard_size indica a Elasticsearch quanti documenti (al massimo) raccogliere da ogni shard.

L’esempio seguente limita il numero di documenti raccolti in ogni shard a 1.000 e poi raggruppa i documenti in base a un’aggregazione di termini:

GET kibana_sample_data_logs/_search
{
  "size": 0,
  "aggs": {
    "sample": {
      "sampler": {
        "shard_size": 1000
      },
      "aggs": {
        "terms": {
          "terms": {
            "field": "agent.keyword"
          }
        }
      }
    }
  }
} 

Risposta di esempio

...
"aggregations" : {
  "sample" : {
    "doc_count" : 1000,
    "terms" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
          "doc_count" : 368
        },
        {
          "key" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24",
          "doc_count" : 329
        },
        {
          "key" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)",
          "doc_count" : 303
        }
      ]
    }
  }
 }
} 

L’aggregazione diversified_sampler consente di ridurre la distorsione nella distribuzione del pool di campioni. È possibile utilizzare l’impostazione del campo per controllare il numero massimo di documenti raccolti in uno shard che condividono un valore comune:

GET kibana_sample_data_logs/_search
{
  "size": 0,
  "aggs": {
    "sample": {
      "diversified_sampler": {
        "shard_size": 1000,
        "field": "response.keyword"
      },
      "aggs": {
        "terms": {
          "terms": {
            "field": "agent.keyword"
          }
        }
      }
    }
  }
} 

Risposta di esempio

...
"aggregations" : {
  "sample" : {
    "doc_count" : 3,
    "terms" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
          "doc_count" : 2
        },
        {
          "key" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)",
          "doc_count" : 1
        }
      ]
    }
  }
 }
} 

significant_terms, significant_text

L’aggregazione significant_terms consente di individuare le occorrenze di termini insoliti o interessanti in un sottoinsieme filtrato rispetto al resto dei dati di un indice.

L’insieme di primo piano è l’insieme di documenti filtrati. Un insieme di sfondo è l’insieme di tutti i documenti di un indice. L’aggregazione significant_terms esamina tutti i documenti dell’insieme in primo piano e trova un punteggio per le occorrenze significative rispetto ai documenti dell’insieme in secondo piano.

Nei dati di web log di esempio, ogni documento ha un campo contenente l’user-agent del visitatore. Questo esempio cerca tutte le richieste provenienti da un sistema operativo iOS. Un’aggregazione di termini regolari su questo insieme in primo piano restituisce Firefox perché ha il maggior numero di documenti in questo bucket. D’altra parte, un’aggregazione significant_terms restituisce Internet Explorer (IE) perché IE ha una presenza significativamente maggiore nell’insieme in primo piano rispetto all’insieme in background.

GET kibana_sample_data_logs/_search
{
  "size": 0,
  "query": {
    "terms": {
      "machine.os.keyword": [
        "ios"
      ]
    }
  },
  "aggs": {
    "significant_response_codes": {
      "significant_terms": {
        "field": "agent.keyword"
      }
    }
  }
} 

Risposta di esempio

...
"aggregations" : {
  "significant_response_codes" : {
    "doc_count" : 2737,
    "bg_count" : 14074,
    "buckets" : [
      {
        "key" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)",
        "doc_count" : 818,
        "score" : 0.01462731514608217,
        "bg_count" : 4010
      },
      {
        "key" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
        "doc_count" : 1067,
        "score" : 0.009062566630410223,
        "bg_count" : 5362
      }
    ]
  }
 }
} 

Se l’aggregazione significant_terms non restituisce alcun risultato, è possibile che i risultati non siano stati filtrati con una query. In alternativa, la distribuzione dei termini nell’insieme in primo piano potrebbe essere la stessa dell’insieme di sfondo, il che implica che non c’è nulla di insolito nell’insieme in primo piano.

L’aggregazione significant_text è simile all’aggregazione significant_terms, ma riguarda i campi di testo grezzo. Il testo significativo misura la variazione di popolarità misurata tra l’insieme in primo piano e quello in secondo piano utilizzando l’analisi statistica. Ad esempio, potrebbe suggerire Tesla quando si cerca l’acronimo TSLA.

L’aggregazione significant_text rianalizza al volo il testo di partenza, filtrando i dati rumorosi come i paragrafi duplicati, le intestazioni e i piè di pagina boilerplate e così via, che potrebbero altrimenti falsare i risultati.

La rianalisi di insiemi di dati ad alta cardinalità può essere un’operazione che richiede molta CPU. Si consiglia di utilizzare l’aggregazione significant_text all’interno di un’aggregazione sampler per limitare l’analisi a una piccola selezione di documenti con le migliori corrispondenze, per esempio 200.

È possibile impostare i seguenti parametri:

  • min_doc_count: restituisce i risultati che corrispondono a più di un numero configurato di risultati principali. Si consiglia di non impostare il numero minimo di documenti a 1, perché tende a restituire termini che sono errori di battitura o di ortografia. Trovare più di un’istanza di un termine aiuta a capire che il significato non è il risultato di un singolo incidente. Il valore predefinito di 3 viene utilizzato per fornire un peso minimo di evidenza.
  • shard_size: l’impostazione di un valore elevato aumenta la stabilità (e la precisione) a scapito delle prestazioni di calcolo.
  • shard_min_doc_count: se il testo contiene molte parole a bassa frequenza e non vi interessano (ad esempio i refusi), potete impostare il parametro shard_min_doc_count per filtrare i termini candidati a livello di shard con una ragionevole certezza di non raggiungere il min_doc_count richiesto anche dopo aver unito le frequenze locali significative del testo. Il valore predefinito è 1, che non ha alcun impatto finché non viene impostato esplicitamente. Si consiglia di impostare questo valore molto più basso del valore min_doc_count.

Si supponga di avere l’opera completa di Shakespeare indicizzata in un cluster Elasticsearch. Potete scaricare il dataset qui. È possibile trovare testi significativi in relazione alla parola “breathe” nel campo text_entry:

GET shakespeare/_search
{
  "query": {
    "match": {
      "text_entry": "breathe"
    }
  },
  "aggregations": {
    "my_sample": {
      "sampler": {
        "shard_size": 100
      },
      "aggregations": {
        "keywords": {
          "significant_text": {
            "field": "text_entry",
            "min_doc_count": 4
          }
        }
      }
    }
  }
} 

Risposta di esempio

"aggregations" : {
  "my_sample" : {
    "doc_count" : 59,
    "keywords" : {
      "doc_count" : 59,
      "bg_count" : 111396,
      "buckets" : [
        {
          "key" : "breathe",
          "doc_count" : 59,
          "score" : 1887.0677966101694,
          "bg_count" : 59
        },
        {
          "key" : "air",
          "doc_count" : 4,
          "score" : 2.641295376716233,
          "bg_count" : 189
        },
        {
          "key" : "dead",
          "doc_count" : 4,
          "score" : 0.9665839666414213,
          "bg_count" : 495
        },
        {
          "key" : "life",
          "doc_count" : 5,
          "score" : 0.9090787433467572,
          "bg_count" : 805
        }
      ]
    }
  }
 }
} 

I testi più significativi in relazione al respiro sono aria, morte e vita.

L’aggregazione significant_text ha le seguenti limitazioni:

  • non supporta le aggregazioni figlio perché le aggregazioni figlio hanno un costo di memoria elevato. Come soluzione, è possibile aggiungere una query successiva utilizzando un’aggregazione di termini con una clausola include e un’aggregazione figlio.
  • non supporta gli oggetti annidati perché lavora con l’origine JSON del documento.
  • il conteggio dei documenti potrebbe presentare alcune imprecisioni (in genere piccole), poiché si basa sulla somma dei campioni restituiti da ogni shard. È possibile utilizzare il parametro shard_size per regolare con precisione il compromesso tra precisione e prestazioni. Per impostazione predefinita, il parametro shard_size è impostato a -1 per stimare automaticamente il numero di frammenti e il parametro size.

Per entrambe le aggregazioni significant_terms e significant_text, la fonte predefinita di informazioni statistiche per le frequenze dei termini di sfondo è l’intero indice. È possibile restringere l’ambito con un filtro di sfondo per ottenere una maggiore precisione:

GET shakespeare/_search
{
  "query": {
    "match": {
      "text_entry": "breathe"
    }
  },
  "aggregations": {
    "my_sample": {
      "sampler": {
        "shard_size": 100
      },
      "aggregations": {
        "keywords": {
          "significant_text": {
            "field": "text_entry",
            "background_filter": {
              "term": {
                "speaker": "JOHN OF GAUNT"
              }
            }
          }
        }
      }
    }
  }
} 

missing

Se nell’indice sono presenti documenti che non contengono affatto il campo aggregante o il campo aggregante ha un valore NULL, utilizzare il parametro missing per specificare il nome del bucket in cui inserire tali documenti.

L’esempio seguente aggiunge tutti i valori mancanti a un bucket denominato “N/A”:

GET kibana_sample_data_logs/_search
{
  "size": 0,
  "aggs": {
    "response_codes": {
      "terms": {
        "field": "response.keyword",
        "size": 10,
        "missing": "N/A"
      }
  }
} 

Poiché il valore predefinito del parametro min_doc_count è 1, il parametro mancante non restituisce alcun bucket nella risposta. Impostare il parametro min_doc_count a 0 per visualizzare il bucket “N/A” nella risposta:

GET kibana_sample_data_logs/_search
{
  "size": 0,
  "aggs": {
    "response_codes": {
      "terms": {
        "field": "response.keyword",
        "size": 10,
        "missing": "N/A",
        "min_doc_count": 0
      }
    }
  }
} 

Risposta di esempio

...
"aggregations" : {
  "response_codes" : {
    "doc_count_error_upper_bound" : 0,
    "sum_other_doc_count" : 0,
    "buckets" : [
      {
        "key" : "200",
        "doc_count" : 12832
      },
      {
        "key" : "404",
        "doc_count" : 801
      },
      {
        "key" : "503",
        "doc_count" : 441
      },
      {
        "key" : "N/A",
        "doc_count" : 0
      }
    ]
  }
 }
} 

More To Explore

Elasticsearch

Elasticsearch: aggregazioni a bucket [parte 1]

Con le aggregazioni a bucket di Elasticsearch possiamo creare gruppi di documenti. In questo articolo ci concentreremo principalmente sulle aggregazioni basate sui campi di tipo keyword presenti negli indici. Utilizzeremo diversi esempi per capire le principali differenze tra le funzioni di aggregazione disponibili.

Elasticsearch

Elasticsearch: aggregazioni metriche

Oltre alla ricerca testuale, Elasticsearch permette di effettuare analisi sui dati mediante le aggregazioni. Tra le varie tipologie di aggregazione disponibili quelle metriche sono orientate proprio a calcolare statistiche su uno o più campi. Mediante degli esempi vedremo quali informazioni possiamo estrarre con questa tipologia di aggregazione.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Design with MongoDB

Design with MongoDB!!!

Buy the new book that will help you to use MongoDB correctly for your applications. Available now on Amazon!