Elasticsearch 中的术语聚合返回单词而不是完整字段值的桶

Term Aggregations in Elasticsearch Returning Buckets for Words Instead of Full Field Values

我有一个使用术语聚合的弹性搜索查询:

{
    "query" : {
        "match_all" : {}                        
    },
    "aggregations" : {
        "tag" : {
            "terms" : {
                "field": "persona"      
            }
        }
    }
}

查询结果中样本命中的 _source 如下所示:

"_source": {
    "facets": {
        "persona": "research manager",
        "research type": "qualitative"
    },
    "name": "Joe Doe"
}

聚合桶看起来像:

"facets": {
    "tag": {
        "_type": "terms",
        "missing": 0,
        "other": 0,
        "terms": [
            {
                "count": 2,
                "term": "research"
            },
            {
                "count": 2,
                "term": "manager"
            }
        ],
        "total": 4
    }
}

术语聚合考虑的是角色字段中的单词,而不是字段的整个值。这是预期的输出:

...
"terms" : [
      {
        "term" : "research manager",
        "count" : 2
      },
      ...
]
....

我是不是做错了什么?有办法实现吗?

很可能字段 "persona" 已被分析。映射的定义 "sample" 应该证实这一点。 Terms aggregation 适用于非分析字段。如果字段 "persona" 被分析,它在索引中保存为两个不同的词 "research" 和 "manager"。要得到你想要的,你必须将字段 "persona" 更改为 non-analyzed。有关详细信息,请参阅 this。恐怕您无法动态地在映射中进行此更改。您需要使用更新后的映射为所有文档重新编制索引才能使更改生效。

正如 bittusarkar 所提到的,角色领域很可能正在被分析。如果您没有在映射中指定映射或有关该字段的信息,那么 Elasticsearch 会将其动态添加到映射中,类型为 string,默认值为 Standard Analyzer。分析器结合了标准分词器,它比空白分词器做的更多,但本质上,您字段的内容被视为 "bag of words".

通常,对于全文搜索/Elasticsearch 查询,您确实希望对内容进行分析,以便在搜索 "managers" 时匹配 "research manager"。

一种解决方案是使用 multi-fields。关于角色字段的映射片段可能如下所示:

"persona": {
    "type": "multi_field",
    "fields": {
        "persona": { "type": "string" },
        "raw":   { "type": "string", "index": "not_analyzed" }
    }
}

这样您就可以进行如下搜索:

{
    "query" : {
        "match" : {
            "persona" : "Managers"
        }
    }
}

同时您可以使用聚合:

{
    "query" : {
        "match_all" : {}
    },
    "aggregations" : {
        "tag" : {
            "terms" : {
                "field": "persona.raw"      
            }
        }
    }
}

请注意,您使用的是 persona.raw 而不是 persona 术语聚合。