Search 如何搜索Lucene.NET而不显示;顶部n“;达到极限?

Search 如何搜索Lucene.NET而不显示;顶部n“;达到极限?,search,memory,lucene,heap,fragmentation,Search,Memory,Lucene,Heap,Fragmentation,Lucene中的IndexSearcher.Search方法有几个重载。其中有些需要“TopN hits”参数,有些则不需要(这些已过时,将在Lucene.NET 3.0中删除) 那些需要“top n”参数的函数实际上会导致整个可能结果范围的内存预分配。所以,当您甚至无法大致估计返回结果的数量时,唯一的机会就是传递一个随机的大数字,以确保所有查询结果都将返回。由于LOH碎片,这会导致严重的内存压力和泄漏 是否有一种官方的、不过时的搜索方式,而不通过“top n”参数 各位,提前谢谢。我正在使用L

Lucene中的IndexSearcher.Search方法有几个重载。其中有些需要“TopN hits”参数,有些则不需要(这些已过时,将在Lucene.NET 3.0中删除)

那些需要“top n”参数的函数实际上会导致整个可能结果范围的内存预分配。所以,当您甚至无法大致估计返回结果的数量时,唯一的机会就是传递一个随机的大数字,以确保所有查询结果都将返回。由于LOH碎片,这会导致严重的内存压力和泄漏

是否有一种官方的、不过时的搜索方式,而不通过“top n”参数


各位,提前谢谢。

我正在使用Lucene.NET 2.9.2作为这个答案的参考点

您可以构建一个自定义收集器,并将其传递给其中一个搜索重载

使用系统;
使用System.Collections.Generic;
使用Lucene.Net.Index;
使用Lucene.Net.Search;
公共类收集器:收集器{
私有只读列表_docIds=new List();
私人记分员;
私有Int32_docBase;
公共IEnumerable文档ID{
获取{return\u docIds;}
}
公共覆盖无效设置记分器(记分器记分器){
_记分员=记分员;
}
公共覆盖无效收集(Int32文档){
var score=_score.score();

if(_lowerInclusiveScore感谢您的建议。实际上,我们一直在以几乎相同的方式使用收集器,唯一的区别是使用LinkedList而不是List来防止内存在增长时重新分配。这种方法在不需要排序的情况下非常有效。没有搜索()重载,它同时接收收集器和排序对象。当使用排序时,我们强制Lucene使用默认的TopHitsCollector,它以所描述的方式预先分配内存。也许使用自定义收集器是个好主意,它在Coolect调用时自己进行排序。你认为如何?我会将其更改为同时存储文档id和排序值,并在收集所有结果后进行排序。如果有单个关键字字段作为排序字段,则可以使用FieldCache,它将加载(并缓存)每个段的字段值。必须使用内部读取器(在SetNextrader中传递给您的读取器)为了让缓存正常工作。是的,我想这是最好的方法,但使用字段缓存除外。这会在一个大索引中占用大量内存,而且由于我们必须经常重新打开它,我不希望为了排序几百行而将所有字段数据从索引加载到内存中。所以看起来你的建议基本上是对我问题的回答。谢谢你西蒙:)在IndexReader上调用.Reopen将重用已经打开的段,同样,也将重用已经打开的段读取器。这意味着FieldCache将在内存中已经有这些项,并且不需要访问磁盘来检索排序值。但是它确实会消耗大量内存,是的。Uhm.Reopen()将从用于创建原始读卡器的源返回新的IndexReader(包括用于近实时更新的IndexWriter)。如果未发生任何更改,它将返回相同的实例,并重用任何未更改的段。请记住,从IndexReader.Open获得的IndexReader实际上是一个由多个段读取器组成的DirectoryReader。只要段仍然存在,就重用段读取器(只创建和删除段,从不更新段).