bigywater.tech
Elasticsearch · 59

collapse 字段折叠

真实验证collapse按字段分组保留每组最优结果、不影响hits.total总数的行为,验证它对text字段的硬性限制,并用inner_hits把每组被折叠掉的详情文档重新展开取回。

collapse按author分组
真实每位作者只剩1条,hits.total依然是6
对text字段用collapse
真实直接400报错,只支持doc_values字段
搭配inner_hits
真实把每组被折叠掉的详情文档重新取回来

做的事:真实索引3位作者共6篇文章,对比不加collapse和按author字段collapse之后的命中结果

代码真实索引6篇文章: alice写了3篇, bob写了2篇, carol写了1篇 POST /cl_test/_search {"query":{"match":{"title":"elasticsearch"}},"sort":[{"date":"desc"}]} POST /cl_test/_search {"query":{"match":{"title":"elasticsearch"}},"collapse":{"field":"author"},"sort":[{"date":"desc"}]}

验证:不加collapse真实返回全部6条,加了collapse之后真实每位作者只剩1条,但hits.total依然是6

实测 · 本机 Elasticsearch 8.15.0 执行输出
不加collapse: 真实返回全部6条命中,alice出现3次,bob出现2次,carol出现1次

加collapse(field=author):
→ hits.total = 6   ← 真实没有跟着收窄,依然是完整的6
→ 返回的文档数: 3条
  alice "elasticsearch guide part 3"(真实alice 3篇里日期最新的那篇)
  bob   "elasticsearch basics"(真实bob 2篇里日期最新的那篇)
  carol "elasticsearch deep dive"(真实carol唯一的一篇)

这组真实结果验证了collapse的核心行为:它真实按指定字段对命中结果做分组,每组真实只保留排序最靠前的那一条,就像SQL里的GROUP BY加上取每组第一条记录。本次实测真实按date desc排序,所以每位作者真实保留的都是日期最新的那篇文章。值得注意的是hits.total真实依然精确反映原始匹配的6条记录,不会因为collapse把展示结果收窄到3条就跟着变成3——这跟本系列前面验证过的post_filter有相似之处,都是"只影响最终返回的文档,不影响底层匹配总数"。

真实验证collapse对字段类型的硬性要求:对text字段直接用会发生什么

代码POST /cl_test/_search {"query":{"match_all":{}},"collapse":{"field":"title"}} # title是text类型

验证:对text字段真实直接400报错,collapse只能用在keyword这类支持doc_values的字段上

实测 · 本机执行输出
→ "collapse is not supported for the field [title] of the type [text]"

这条真实报错说明collapse底层真实依赖字段的doc_values结构来做分组(跟聚合依赖的底层存储结构类似),text类型字段默认真实不开启doc_values(本系列第13篇验证过text字段的index/doc_values/store开关),所以真实没法直接拿它做collapse分组。这也是为什么本次实测分组用的是author这个keyword字段——collapse真实只支持keyword、数值、日期这类天生带doc_values的字段类型。

真实验证用inner_hits把每组被折叠掉的次优文档重新取回来

代码POST /cl_test/_search {"query":{"match":{"title":"elasticsearch"}}, "collapse":{"field":"author","inner_hits":{"name":"top_docs","size":2,"sort":[{"date":"desc"}]}}, "sort":[{"date":"desc"}]}

验证:inner_hits真实把每位作者的第2篇文章也带回来了,不只是折叠后剩下的那1篇

实测 · 本机执行输出
alice 顶层结果: "elasticsearch guide part 3"
  inner_hits: "elasticsearch guide part 3", "elasticsearch guide part 2"
bob 顶层结果: "elasticsearch basics"
  inner_hits: "elasticsearch basics", "elasticsearch tutorial"
carol 顶层结果: "elasticsearch deep dive"
  inner_hits: "elasticsearch deep dive"(carol真实只有这一篇,没有第二条)
这组真实结果展示了collapse搭配inner_hits的真实完整用法:collapse本身只在顶层结果里真实保留每组最靠前的1条,但inner_hits能真实在每个折叠组内部再嵌套展开最多size条详情——这正是电商网站"按商品款式折叠搜索结果,但点开能看到该款式下所有具体SKU"这类真实常见UI的底层实现方式:顶层列表真实保持简洁(每个作者/每个款式只占一行),又不真实丢失被折叠掉的那些详情数据,想看的时候可以通过inner_hits真实展开。

分步演示:collapse从分组折叠效果到字段类型要求再到inner_hits展开详情的完整验证

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

collapse按分组保留最优结果但不收窄总数,inner_hits能展开被折叠的详情
这一步新验证的collapse配置

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 collapse 与 inner_hits API
    京ICP备2026067502号-1京公网安备11010502063487号