Solr Group源码分析

2022-07-28 19:22:27 浏览数 (1)

官方文档

https://solr.apache.org/guide/8_6/result-grouping.html

功能描述

近似于facet, 相当于facet结果的每个桶里追加上几个桶内的文档.

几个关键点

  1. 分桶字段(group.field)
  2. 关于桶的设置
    1. 返回桶的最大数量(rows)
    2. 桶的排序方式(sort)
  3. 关于每个桶返回文档的设置
    1. 桶内返回文档的最大数量(group.limit)
    2. 桶内文档的排序方式(group.sort)
    3. 桶内文档返回哪些字段 (fl)

执行过程

分两阶段执行:

阶段1: 确定返回哪些桶, 以及桶的排序. 桶的排序只与sort参数有关, group.sort阶段1不会用到.

阶段2: 给每个桶补充文档.

阶段1

数据节点

Query: 原始查询q.

Collector: FirstPassGroupingCollector

数据节点在阶段1获取自己shard内的Top N个桶(也称为group).

可以看成是先把group.field的所有取值values枚举出来, 生成N个桶, 每个桶代表一个值value. 如果一个文档的group.field取值为value, 那么他就被装到值为value的桶里.

每个桶有一个sortValue, 这个sortValue就是桶内所有文档的最佳排序值. 比如说sort=score desc, 那么每个桶的排序值就是桶内所有文档得分取max. 比如说sort=field1 asc, 那么每个桶的排序值就是桶内所有文档的field1字段值取min.

然后所有的桶根据sort方式, 按照桶的排序值排序, 取 Top rows个, 就得到了最终要返回桶的列表.

协调节点

Merge处理器: SearchGroupShardResponseProcessor.

每个shard返回自己的Top N个group时, 每个group会带上其最佳文档排序值(即sortValue).

协调节点对多个shard返回的桶列表做合并, 把每个数据节点返回的 Top N个桶最终合并为全局的Top N个桶.

合并的时候也是根据sort排序方式和每个桶的最佳文档排序值作为根据.

综合数据节点和协调节点的处理可以看出, 最终返回桶的列表只和group.field, rows, sort 3个参数有关.

阶段2

数据节点

Query: 原始查询q.

Collector: TopGroupsCollector(extends SecondPassGroupingCollector)

核心逻辑就是给每个桶创建一个collector, collector的numHits设置为group.limit, collector的排序方式是group.sort. 用查询q重新查一遍, 每个文档先获取其group.field值, 根据值可以确定当前文档属于哪个桶, 然后把这个文档加入该桶(在每个桶内是以group.sort方式给所有文档排序的, 最终每个桶取Top group.limit 个文档.).

协调节点

Merge处理器: TopGroupsShardResponseProcessor.

这块源码没细看, 猜也能猜到:

应该以group为粒度合并多个shard返回的文档列表. 具体的合并逻辑就和正常搜索合并多个shard的文档列表一样的, 无非是每个group下的文档列表单独走一遍合并逻辑.

0 人点赞