如何使用Lucene的DistinctValuesCollector?请求示例代码
正确使用Lucene DistinctValuesCollector获取字段唯一值
你的代码存在两处核心问题:
- 错误地将
TermGroupSelector同时用作分组选择器和值选择器,不符合DistinctValuesCollector的设计逻辑 - 初始化
SearchGroup时未指定有效分组基准值,导致无法正确归集结果
结合你已有的索引方式(同时存储TextField和SortedDocValuesField),以下是正确的Kotlin实现示例:
标准实现代码
import org.apache.lucene.search.DistinctValuesCollector import org.apache.lucene.search.grouping.TermGroupSelector import org.apache.lucene.search.grouping.TermValueSelector import org.apache.lucene.search.grouping.SearchGroup import org.apache.lucene.util.BytesRef // 1. 定义虚拟分组选择器:全局收集唯一值时,用固定虚拟字段让所有文档归为一组 val groupSelector = TermGroupSelector("__global_group__") // 2. 定义值选择器:指定要提取唯一值的目标字段 val valueSelector = TermValueSelector(PROJEKTSTATUS.name) // 3. 初始化搜索分组:使用空BytesRef作为虚拟分组的基准值 val searchGroup = SearchGroup<BytesRef>(BytesRef.EMPTY_BYTES_REF) val groups = mutableListOf(searchGroup) // 4. 创建收集器实例并执行搜索 val distinctValuesCollector = DistinctValuesCollector(groupSelector, groups, valueSelector) searcher.search(query, distinctValuesCollector) // 5. 提取并转换唯一值 val distinctStatusValues = distinctValuesCollector.groups[0].values.map { it.utf8ToString() }
关键说明
- 虚拟分组的必要性:
DistinctValuesCollector本质是基于分组去重,若无需按其他字段分组,必须用虚拟分组将所有文档归集到同一组中 - 值选择器的正确类型:必须使用
TermValueSelector指定目标字段,而非TermGroupSelector,前者负责提取需要去重的字段值 - 索引匹配要求:你已正确添加
SortedDocValuesField,这是TermValueSelector高效读取字段值的必要前提
轻量替代方案
如果仅需全局唯一值、无需分组功能,可直接使用SortedSetDocValues实现,代码更简洁:
import org.apache.lucene.index.SortedSetDocValues val sortedSet = searcher.indexReader.getSortedSetDocValues(PROJEKTSTATUS.name) val distinctStatusValues = mutableListOf<String>() if (sortedSet != null) { var ordinal = sortedSet.nextOrd() while (ordinal != -1) { distinctStatusValues.add(sortedSet.lookupOrd(ordinal).utf8ToString()) ordinal = sortedSet.nextOrd() } }
内容的提问来源于stack exchange,提问作者Andras Hatvani
相关产品推荐
相关产品推荐

