Elasticsearch中的术语聚合返回桶的单词而不是全场值

时间:2015-10-16 20:55:00

标签: aggregation elasticsearch

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

{
    "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
      },
      ...
]
....

我做错了吗?有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:4)

正如bittusarkar所提到的,人物角色最有可能被分析。如果您未在映射中指定该字段的映射或信息,则Elasticsearch会将其动态添加到映射中,类型为string,默认为Standard Analyzer。分析器包含标准的标记器,它比空白标记器更多,但基本上你的字段内容被视为一个单词"。

通常,对于全文搜索/ Elasticsearch查询,您确实希望对内容进行分析,以便您可以匹配"研究经理"当你搜索"经理"例如。

一种解决方案是使用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代替persona.raw代替聚合这一术语。

答案 1 :(得分:1)

最有可能对“人物角色”字段进行分析。映射“样本”的定义应该确认它。 Terms aggregation适用于未分析的字段。如果分析字段“persona”,则将其作为两个不同的单词“research”和“manager”保存在索引中。为了获得你想要的东西,你必须将字段“persona”更改为未分析。有关详细信息,请参阅this。我担心你不能动态地在映射中进行这种改变。您需要使用更新的映射重新索引所有文档,以使更改生效。