【问题标题】:What's the most efficient way to retrieve all matching documents from a query in Lucene, unsorted?从Lucene中的查询中检索所有匹配文档的最有效方法是什么,未排序?
【发布时间】:2011-07-23 00:56:11
【问题描述】:

我希望执行查询以维护内部完整性;例如,从索引中删除特定字段/值的所有痕迹。因此,重要的是我要找到 所有 个匹配的文档(不仅仅是前 n 个文档),但它们返回的顺序无关紧要。

根据文档,看起来我需要使用 Searcher.Search( Query, Collector ) 方法,但是没有内置的 Collector 类可以满足我的需要。

我应该为此派生自己的 Collector 吗?这样做时我需要记住什么?

【问题讨论】:

  • 如果您想返回所有结果,请记住这一点:forums.alfresco.com/en/viewtopic.php?t=13381
  • @Rodrigo 你能更具体一点吗?我阅读了该线程,但它似乎与权限检查有关。你能解释一下这与我的问题有什么关系吗?

标签: c# .net lucene lucene.net


【解决方案1】:

事实证明,这比我预期的要容易得多。我刚刚使用了http://lucene.apache.org/java/2_9_0/api/core/org/apache/lucene/search/Collector.html 的示例实现,并将传递给Collect() 方法的文档编号记录在一个List 中,将其公开为Docs 的公共属性。

然后我简单地迭代这个属性,将数字传递回Searcher 以获得正确的Document

var searcher = new IndexSearcher( reader );
var collector = new IntegralCollector(); // my custom Collector
searcher.Search( query, collector );
var result = new Document[ collector.Docs.Count ];
for ( int i = 0; i < collector.Docs.Count; i++ )
    result[ i ] = searcher.Doc( collector.Docs[ i ] );
searcher.Close(); // this is probably not needed
reader.Close();

到目前为止,它似乎在初步测试中运行良好。

更新:这是IntegralCollector的代码:

internal class IntegralCollector: Lucene.Net.Search.Collector {
    private int _docBase;

    private List<int> _docs = new List<int>();
    public List<int> Docs {
        get { return _docs; }
    }

    public override bool AcceptsDocsOutOfOrder() {
        return true;
    }

    public override void Collect( int doc ) {
        _docs.Add( _docBase + doc );
    }

    public override void SetNextReader( Lucene.Net.Index.IndexReader reader, int docBase ) {
        _docBase = docBase;
    }

    public override void SetScorer( Lucene.Net.Search.Scorer scorer ) {
    }
}

【讨论】:

  • 请记住使用传递给SetNextReader 的docBase 值,因为传递给Collect 的文档ID 特定于当前阅读器(来自SetNextReader)。您需要使用 (docBase+doc) 来计算要与最顶层阅读器一起使用的 ID,即打开 IndexSearcher 时使用的那个。
  • 另外,如果您想删除匹配的文档,请不要忘记IndexWriter.DeleteDocuments(Query)
  • @Simon - 谢谢,当我开始得到不稳定的结果时,我自己想通了。另外,删除只是一个例子,我确实需要在我的真实应用程序中检索文档。
【解决方案2】:

如果您只是想获取索引中的所有 Document 对象,则无需编写命中收集器。只需从 0 循环到 maxDoc() 并在每个 doc id 上调用 reader.document(),确保跳过已删除的文档:

for (int i=0; i<reader.maxDoc(); i++) {
   if (reader.isDeleted(i))
      continue;
   results[i] = reader.document(i);
}

【讨论】:

  • 谢谢,但我对实际执行查询感兴趣,而不仅仅是获取索引中的所有文档。
猜你喜欢
  • 2015-02-04
  • 2023-03-30
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
  • 2015-12-11
  • 2014-02-03
相关资源
最近更新 更多