以下是我试图解决的问题:
我使用MultiReader
一起查询所有索引,并且我能够使用ReaderUtil
找出命中来自哪个子索引。到目前为止一切顺利,但问题在于:
为了执行(相当复杂的)合并逻辑,我需要所有子指标中的文档以及与原始查询中至少一个文档匹配的任何键。
以下是一个例子:
索引1
1:{key: "foo", name: "Name A", something: 42}
2:{key: "bar", something: 2}
索引2
27:{key: "foo", something: 2}
索引3
102:{key: "foo", name: "Name B"}
103:{key: "bar", something: 999}
现在,如果我要对名称"Name A"
执行查询,我只会从索引1获取文档1 。
我真正需要的是所有索引中包含该查询中所有键的所有文档,这些文档都是键foo
的文档:
基于name: "Name A"
的原始查询。
我可以在没有2个单独查询的情况下实现此目的,第二个是基于第一个检索到的密钥的大量OR
吗?有更有效的方法吗?
答案 0 :(得分:0)
好的,这是我如何让它发挥作用:
将TermFirstPassGroupingCollector
与群组字段id
一起使用,并使用实际搜索查询执行搜索(例如name: Name A
)
TermFirstPassGroupingCollector firstPassCollector = new TermFirstPassGroupingCollector(
"<grouping field name, e.g. id>",
Sort.INDEXORDER,
x);
searcher.search(query, firstPassCollector);
Collection<SearchGroup<String>> firstPassResult = firstPassCollector.getTopGroups(0, false)
然后,使用第二个传递收集器,并使用MatchAllDocsQuery
收集所有组中的所有字段:
TermSecondPassGroupingCollector secondPassCollector = new TermSecondPassGroupingCollector(
fieldNaming.getIdFieldName(),
firstPassResult,
Sort.INDEXORDER,
Sort.INDEXORDER,
maxDocsPerGroup,
false,
false,
false);
searcher.search(new MatchAllDocsQuery(), secondPassCollector);
我现在可以遍历所有(匹配的)组,并获取每个组中的所有文档,无论它是否明确匹配:
for (GroupDocs groupDocs : documentGroups) {
if (groupDocs.totalHits == 0) {
continue;
}
for (int doc : groupDocs.scoreDocs) {
Document document = reader.document(doc);
...
}
}
问题解决了。确保你像处理getTopGroups()
的第一个收集者null
一样处理怪异。