Elasticsearch 中的多字段聚合
Posted
技术标签:
【中文标题】Elasticsearch 中的多字段聚合【英文标题】:Multi-field aggregation in Elasticsearch 【发布时间】:2021-02-14 09:10:31 【问题描述】:我在 elasticsearch 中有一个文档索引,每个文档有 480 个字段。我要做的是搜索一个词(例如“apple”),并获取其值与搜索词匹配的所有唯一字段名称。 因此,如果我的文档是:
"field1": "123",
"field2": "apple stock",
"field3": "red apple",
,
"field1": "apple",
"field2": "apple stock",
"field3": "green apple",
作为查询的结果,我希望得到的是这样的聚合:
"field1": ["apple"],
"field2": ["apple stock"],
"field3": ["red apple", "green apple"]
由于每个文档都有大约 480 个字段,我更喜欢执行 multi_match 查询,而不是包含所有字段的过滤器:
"query":
"multi_match":
"query": "apple",
"type": "phrase"
在 elasticsearch 中是否可以进行此查询?
【问题讨论】:
【参考方案1】:既然你“不知道你不知道什么”,你可能不得不求助于scripted metric aggregation:
POST myindex/_search
"size": 0,
"query":
"multi_match":
"query": "apple",
"type": "phrase"
,
"aggs":
"fields_breakdown":
"scripted_metric":
"params":
"phrase": "apple"
,
"init_script": "state.key_map = [:];",
"map_script": """
for (def pair : params._source.entrySet())
def val = pair.getValue();
if (!(val instanceof String) || !val.toLowerCase().contains(params.phrase.toLowerCase()))
continue;
def key = pair.getKey();
if (!state.key_map.containsKey(key))
state.key_map[key] = [val];
else if (!state.key_map[key].contains(val))
state.key_map[key].add(val);
""",
"combine_script": "return state",
"reduce_script": "return states"
此代码无法很好地扩展(取决于您的索引大小),因此请谨慎使用它,也许可以分批使用(通过使用更严格的查询或限制一次聚合的字段数)。
顺便说一句,I proposed a solution 不久前用于过滤类似术语的聚合中的子字符串 - 这里可能与您相关。
【讨论】:
谢谢。我用邮递员尝试了上面的查询,它崩溃了,可能是因为索引大小。 这就是我所担心的。【参考方案2】:我实际上正在考虑使用highlight
来获取与查询匹配的值,然后在代码中删除重复项。
"query":
"multi_match":
"query": "apple",
"type": "phrase"
,
"highlight":
"pre_tags": [
""
],
"post_tags": [
""
],
"fields":
"*":
【讨论】:
那很好。然后,您可以使用 elastic-dump 下载/流式传输所有内容,然后以您选择的语言对其进行后期处理。以上是关于Elasticsearch 中的多字段聚合的主要内容,如果未能解决你的问题,请参考以下文章
Elasticsearch:Elasticsearch 中的父级和兄弟级聚合
Elasticsearch:如何使 Elasticsearch 和 Kibana 中的文本字段可聚合?
Elasticsearch:如何使 Elasticsearch 和 Kibana 中的文本字段可聚合?
elasticsearch - 聚合返回 key 中的术语,但不是完整的字段,我怎样才能返回完整的字段?