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
术语聚合。
我有一个使用术语聚合的弹性搜索查询:
{
"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
术语聚合。