Jak query distinct field values v ElasticSearch

Předpokládejme, že máme ElasticSearch index nazvaný strings s fieldem pattern typu {"type": "keyword"}.

Získání top N hodnot sloupce

Pokud chceme získat top N ( 12 v našem příkladu) entries, tj. patterns, které jsou přítomny v nejvíce dokumentech, můžeme použít tento query:

terms_aggregation_query.json
{
    "aggs" : {
        "patterns" : {
            "terms" : {
                "field" : "pattern.keyword",
                "size": 12
            }
        }
    }
}

Full example v Pythonu:

es_terms_example.py
from elasticsearch import Elasticsearch

es = Elasticsearch()

result = es.search(index="strings", body={
    "aggs" : {
        "patterns" : {
            "terms" : {
                "field" : "pattern.keyword",
                "size": 12
            }
        }
    }
})
for aggregation in result["aggregations"]["patterns"]["buckets"]:
    print(aggregation) # e.g. {'key': 'mypattern, 'doc_count': 2802}

Viz terms aggregation documentation pro více info.

Získání všech distinct hodnot sloupce

Získání všech hodnot je o něco složitější, protože potřebujeme použít composite aggregation, který vrací after_key pro paginaci query.

Tento Python helper function automaticky paginuje query s konfigurovatelnou page size:

es_iterate_distinct.py
from elasticsearch import Elasticsearch

es = Elasticsearch()

def iterate_distinct_field(es, fieldname, pagesize=250, **kwargs):
    """
    Helper to get all distinct values from ElasticSearch
    (ordered by number of occurrences)
    """
    compositeQuery = {
        "size": pagesize,
        "sources": [{
                fieldname: {
                    "terms": {
                        "field": fieldname
                    }
                }
            }
        ]
    }
    # Iterate over pages
    while True:
        result = es.search(**kwargs, body={
            "aggs": {
                "values": {
                    "composite": compositeQuery
                }
            }
        })
        # Yield each bucket
        for aggregation in result["aggregations"]["values"]["buckets"]:
            yield aggregation
        # Set "after" field
        if "after_key" in result["aggregations"]["values"]:
            compositeQuery["after"] = \
                result["aggregations"]["values"]["after_key"]
        else: # Finished!
            break

# Usage example
for result in iterate_distinct_field(es, fieldname="pattern.keyword", index="strings"):
    print(result) # e.g. {'key': {'pattern': 'mypattern'}, 'doc_count': 315}

Podívejte se na podobné články podle kategorie: Databases ElasticSearch Python