使用Lucene索引自定义收集器的方式

dam*_*max 6 lucene

有人可以帮我解决在Lucene中使用抽象收集器类的自定义实现的方法吗?

我已经实现了两种使用一些测试文本查询索引的方法:

1.总命中数是2.两个文件名都相同,因此结果大小为1,因为我将它们保存在一个集合中.

TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
LOG.info("Total hits " + topDocs.totalHits);
ScoreDoc[] scoreDosArray = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDosArray) {
    Document doc = searcher.doc(scoreDoc.doc);
    String fileName = doc.get(FILENAME_FIELD);
    results.add(fileName);
}
Run Code Online (Sandbox Code Playgroud)

2.CountCollect是eq to 2.我从Collector的collect方法中获取文件名的两个文件都是唯一的,因此最终结果大小也是eq到2. CountNextReader变量在逻辑结尾处是eq到10.

private Set<String> doStreamingSearch(final IndexSearcher searcher, Query query) throws IOException {
    final Set<String> results = new HashSet<String>();
    Collector collector = new Collector() {
        private int base;
        private Scorer scorer;
        private int countCollect;
        private int countNextReader;

        @Override
        public void collect(int doc) throws IOException {
            Document document = searcher.doc(doc);
            String filename = document.get(FILENAME_FIELD);
            results.add(filename);
            countCollect++;
        }

        @Override
        public boolean acceptsDocsOutOfOrder() {
            return true;
        }

        @Override
        public void setScorer(Scorer scorer) throws IOException {
            this.scorer = scorer;
        }

        @Override
        public void setNextReader(AtomicReaderContext ctx) throws IOException {
            this.base = ctx.docBase;
            countNextReader++;
        }

        @Override
        public String toString() {
            LOG.info("CountCollect: " + countCollect);
            LOG.info("CountNextReader: " + countNextReader);
            return null;
        }
    };
    searcher.search(query, collector);
    collector.toString();
    return results;
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么在collect方法中我得到不同的文件和不同的文件名与以前的实现相比?我期待同样的结果,或者?

jav*_*nna 12

Collector#collect方法是搜索请求的热点.它会调用与查询匹配的每个文档,而不仅仅是您获取的文档.实际上,您通常只返回顶级文档,这些文档实际上是您向用户显示的文档.

我建议不要做以下事情:

TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
Run Code Online (Sandbox Code Playgroud)

这将迫使lucene返回太多文件.

无论如何,如果您只有两个匹配的文档(或者您要求匹配的所有文档),您获取的文档数量和对collect方法的调用次数应该相同.

这种setNextReader方法完全不同,你不应该太在乎.看看这篇文章,如果你想知道更多关于AtomicReader等.为了简短起见,Lucene将数据存储为段,这些段是迷你可搜索的反向索引.每个查询按顺序在每个段上执行.每次搜索切换到下一个段时,setNextReader都会调用该方法以允许在段中的段级别执行操作Collector.例如,内部lucene文档id仅在段内是唯一的,因此您需要添加docBase它以使其在整个索引中唯一.这就是为什么您需要在细分变化时将其存储起来并将其考虑在内.您的countNextReader变量只包含已为您的查询分析的段数,它与您的文档没有任何关系.

深入研究您的Collector代码我还注意到您没有考虑docBase通过id检索文档的时间.这应该解决它:

Document document = searcher.doc(doc + docBase);
Run Code Online (Sandbox Code Playgroud)

还要记住,在a中加载存储的字段Collector并不是一件明智的事情.它会让您的搜索速度变慢,因为存储的字段是从磁盘加载的.您通常仅为要返回的文档子集加载存储的字段.在一个Collector你通常加载有用的信息,如有效载荷或类似的东西,通常也使用lucene字段缓存.

  • 在最新版本的Lucene中,`Collector`是一个接口,没有`collect`.相反(就我对问题的理解而言),应该覆盖[`Collector#getLeafCollector`](https://lucene.apache.org/core/6_1_0/core/org/apache/lucene/search/Collector .html #getLeafCollector-org.apache.lucene.index.LeafReaderContext-)并使其返回自定义[`LeafCollector`](https://lucene.apache.org/core/6_1_0/core/org/apache/lucene/搜索/ LeafCollector.html). (3认同)