ElasticSearch 5.6.16:查找不同字段值匹配的关联文档
解决ElasticSearch 5.6.16中关联item与relation文档的聚合问题
需求说明
在ElasticSearch 5.6.16索引中,需要将item类型文档的_itemId字段与relation类型文档的_relatedId字段做关联,把匹配的item和对应的所有relation文档分组,期望结果形式如下:
{i_1, r_1, r_2} {i_2, r_3}
索引数据
[ { "_type": "item", "_itemId": "i_1" }, { "_type": "item", "_itemId": "i_2" }, { "_type": "relation", "_relId": "r_1", "_relatedId": "i_1" }, { "_type": "relation", "_relId": "r_2", "_relatedId": "i_1" }, { "_type": "relation", "_relId": "r_3", "_relatedId": "i_2" } ]
映射信息
{ "item": { "_itemId": { "type": "keyword" } }, "relation": { "_relatedId": { "type": "keyword" } } }
原查询问题
你之前的聚合查询仅按_itemId字段聚合,只能返回item类型的文档,无法关联获取对应的relation数据。
解决方案
利用ElasticSearch的script生成统一关联键+多层聚合的方式,一次性完成分组关联,查询语句如下:
{ "size": 0, "aggs": { "group_by_association": { "terms": { "script": """ if (doc['_type'].value == 'item') { return doc['_itemId'].value; } else if (doc['_type'].value == 'relation') { return doc['_relatedId'].value; } return ''; """, "size": 1000 }, "aggs": { "matched_item": { "filter": { "term": { "_type": "item" } }, "aggs": { "item_info": { "top_hits": { "_source": ["_itemId"], "size": 1 } } } }, "related_relations": { "filter": { "term": { "_type": "relation" } }, "aggs": { "relation_info": { "top_hits": { "_source": ["_relId"], "size": 100 } } } } } } } }
查询说明
- 统一关联键:通过script判断文档类型,
item类型取_itemId,relation类型取_relatedId,以此作为分组的key,确保匹配的文档会被分到同一个bucket中。 - 分层过滤聚合:每个分组下再通过
filter分别筛选item和relation类型的文档,用top_hits取出对应字段(item只取1条即可,relation取所有匹配的)。 - 结果整理:返回的聚合结果中,每个bucket的
key就是关联ID(如i_1),matched_item下是对应的item信息,related_relations下是所有关联的relation ID,按需提取即可得到期望的分组形式。
注意事项
- ElasticSearch 5.6默认可能禁用inline script,需要在
elasticsearch.yml中配置script.inline: on,或者将script保存为stored script后调用。
内容的提问来源于stack exchange,提问作者iriv
相关产品推荐
相关产品推荐

