如何在 ElasticSearch 中查询不同的字段值

假设我们有一个名为 strings 的 ElasticSearch 索引,其中包含 {"type": "keyword"} 类型的 pattern 字段。

获取列的前 N 个值

如果我们想获取前 N 个(在我们的示例中为 12)条目,即出现在最多文档中的 pattern,我们可以使用此查询:

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

Python 完整示例:

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}

请参见 terms 聚合文档了解更多信息。

获取列的所有不同值

获取所有值稍微复杂一些,因为我们需要使用返回 after_key 来分页查询的复合聚合

此 Python 辅助函数将使用可配置的页面大小自动分页查询:

es_iterate_distinct.py
from elasticsearch import Elasticsearch

es = Elasticsearch()

def iterate_distinct_field(es, fieldname, pagesize=250, **kwargs):
    """
    辅助函数:从 ElasticSearch 获取所有不同的值
    (按出现次数排序)
    """
    compositeQuery = {
        "size": pagesize,
        "sources": [{
                fieldname: {
                    "terms": {
                        "field": fieldname
                    }
                }
            }
        ]
    }
    # 迭代页面
    while True:
        result = es.search(**kwargs, body={
            "aggs": {
                "values": {
                    "composite": compositeQuery
                }
            }
        })
        # 生成每个桶
        for aggregation in result["aggregations"]["values"]["buckets"]:
            yield aggregation
        # 设置 "after" 字段
        if "after_key" in result["aggregations"]["values"]:
            compositeQuery["after"] = \
                result["aggregations"]["values"]["after_key"]
        else: # 完成!
            break

# 用法示例
for result in iterate_distinct_field(es, fieldname="pattern.keyword", index="strings"):
    print(result) # 例如 {'key': {'pattern': 'mypattern'}, 'doc_count': 315}

Check out similar posts by category: Databases, ElasticSearch, Python