Elasticsearch 中多字段条件聚合

cwa*_*rny 6 elasticsearch

这是我的 ES 索引中的文档示例:

{ 
    "concepts": [ 
        { 
            "type": "location",
            "entities": [ 
                { "text": "Raleigh" }, 
                { "text": "Damascus" }, 
                { "text": "Brussels" } 
            ] 
        }, 
        { 
            "type": "person", 
            "entities": [ 
                { "text": "Johnny Cash" }, 
                { "text": "Barack Obama" }, 
                { "text": "Vladimir Putin" }, 
                { "text": "John Hancock" } 
            ] 
        }, 
        { 
            "type": "organization", 
            "entities": [ 
                { "text": "WTO" }, 
                { "text": "IMF" }, 
                { "text": "United States of America" } 
            ] 
        } 
    ] 
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试汇总和计算特定概念类型的文档集中每个概念实体的频率。假设我只对聚合“位置”类型的概念实体感兴趣。我的聚合桶将是“concepts.entities.text”,但我只想在“concepts.type”等于“location”时聚合它们。这是我的尝试:

{
    "query": {
        // Whatever query
    },
    "aggs": {
        "location_concept_type": {
            "filter": {
                "term": { "concepts.type": "location" }
            },
            "aggs": {
                "entities": {
                    "terms": { "field": "concepts.hits.text" }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样做的问题是它将从聚合中过滤掉没有任何“位置”类型的概念实体的文档。但是对于确实具有“位置”类型其他类型的概念实体的文档,它将存储所有概念实体,而不管概念类型如何。

我还尝试通过以下方式重组我的文档:

{ 
    "concepts": [ 
        { 
            "type": "location",
            "text": "Raleigh"
        },
        { 
            "type": "location",
            "text": "Damascus"
        },
        { 
            "type": "location",
            "text": "Brussels"
        }, 
        { 
            "type": "person",
            "text": "Johnny Cash"
        },
        { 
            "type": "person",
            "text": "Barack Obama"
        }
        { 
            "type": "person",
            "text": "Vladimir Putin"
        }
        { 
            "type": "person",
            "text": "John Hancock"
        }, 
        { 
            "type": "organization",
            "text": "WTO" 
        },
        { 
            "type": "organization",
            "text": "IMF" 
        },
        { 
            "type": "organization",
            "text": "United States of America" 
        }
    ] 
}
Run Code Online (Sandbox Code Playgroud)

但这也行不通。最后,我不能使用概念类型作为键(我相信这会解决我的问题),因为我还需要能够聚合所有概念类型(并且概念类型的数量可能不确定且不断变化)。

知道如何进行吗?在此先感谢您的帮助。

cwa*_*rny 6

如果您按如下方式构建索引:

{ 
    "concepts": [ 
        { 
            "type": "location",
            "text": "Raleigh"
        },
        { 
            "type": "location",
            "text": "Damascus"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

并将映射中的“概念”字段定义为嵌套对象,您可以应用以下搜索,嵌套聚合中嵌套过滤器聚合:

{
    "query": {
        "match_all": {}
    },
    "aggs": {
        "location_entities": {
            "nested": { "path": "concepts" }
        },
        "aggs": {
            "filtered_aggregation": {
                "filter": { "term": { "concepts.type": "location" } },
                "aggs": {
                    "my_aggregation": {
                        "terms": { "field": "concepts.text" }
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在响应中,您知道您只获取位置实体。这种方法比另一个答案中的“hack”快得多。

从 1.0.4Beta1 版本开始,Elasticsearch 提供了过滤器聚合。用过滤器聚合替换嵌套聚合中的过滤器聚合,您可以按实体类型对聚合进行分桶。