Elasticsearch按字段分组获取每组得分最高的单条记录
按类别获取每组匹配得分最高的单条记录
问题说明
我是Elasticsearch新手,想要实现:在comment字段搜索指定内容后,按category分组,每组只返回匹配得分最高的单条记录。
索引详情
创建索引的请求如下:
PUT commentdetail { "mappings": { "properties": { "category": { "type": "text" }, "comment": { "type": "text" } } } }
示例数据
| category | Comment |
|---|---|
| fruit | I like apple |
| fruit | I like apple and banana |
| fruit | I like banana and apple |
| fruit | I like banana but not apple |
| fruit | I like apple but not banana |
| fruit | I like banana |
| vegetable | I like potato |
| vegetable | I like potato and tomato |
| vegetable | I like tomato and potato |
| vegetable | I like tomato but not potato |
| vegetable | I like potato but not tomato |
| vegetable | I like tomato |
期望结果
当在comment字段搜索"I like"时,希望得到如下结果:
| category | Comment |
|---|---|
| fruit | I like apple |
| vegetable | I like potato |
解决方案
可以通过terms聚合结合top_hits子聚合实现需求,查询语句如下:
GET commentdetail/_search { "size": 0, // 不返回原始搜索结果,只返回聚合结果 "query": { "match_phrase": { "comment": "I like" } }, "aggs": { "group_by_category": { "terms": { "field": "category.keyword", // 用keyword字段分组,避免text分词导致的分组错误 "size": 10 // 根据实际类别数量调整取值 }, "aggs": { "top_comment": { "top_hits": { "size": 1, // 每组仅取1条得分最高的记录 "_source": ["category", "comment"], // 指定返回字段 "sort": [ { "_score": { // 按匹配得分降序排序 "order": "desc" } } ] } } } } } }
结果解析
聚合结果会在aggregations.group_by_category.buckets节点下,每个bucket对应一个分类,其中top_comment.hits.hits[0]就是该分类下得分最高的记录。如果需要更简洁的输出格式,可以对聚合结果做后续整理。
注意:如果创建索引时未给category字段配置keyword子字段,需要先更新映射,否则terms聚合会因text字段分词无法正确分组。
内容的提问来源于stack exchange,提问作者ankur patel
相关产品推荐
相关产品推荐

