lucene - 当我不知道创建时的最大大小时,如何使用 Lucene 的 PriorityQueue?

标签 lucene lucene.net

我为 Lucene.Net 构建了一个自定义收集器,但我不知道如何对结果进行排序(或分页)。每次调用 Collect 时,我都可以将结果添加到内部 PriorityQueue,我认为这是执行此操作的正确方法。

我扩展了 PriorityQueue,但它在创建时需要一个大小参数。您必须在构造函数中调用 Initialize 并传入最大大小。

但是,在收集器中,搜索器仅在获得新结果时调用 Collect,因此我不知道创建 PriorityQueue 时有多少结果。基于此,我不知道如何使 PriorityQueue 工作。

我意识到我可能在这里遗漏了一些简单的东西......

最佳答案

PriorityQueue 不是 SortedListSortedDictionary。 它是一种排序实现,它返回 N 个元素的前 M 个结果(您的 PriorityQueue 的大小)。您可以使用 InsertWithOverflow 添加任意数量的项目,但它只会保存前 M 个元素。

假设您的搜索结果为 1000000 次点击。您会将所有结果返回给用户吗? 更好的方法是将前 10 个元素返回给用户(使用 PriorityQueue(10))并 如果用户请求接下来 10 个结果,您可以使用 PriorityQueue(20) 进行新搜索,并且返回接下来的 10 元素,依此类推。 这是大多数搜索引擎(例如 Google)使用的技巧。

每次调用 Commit 时,我都可以将结果添加到内部 PriorityQueue

我无法理解Commitsearch之间的关系,因此我将附上PriorityQueue的示例用法:

public class CustomQueue : Lucene.Net.Util.PriorityQueue<Document>
{
    public CustomQueue(int maxSize): base()
    {
        Initialize(maxSize);
    }

    public override bool LessThan(Document a, Document b)
    {
        //a.GetField("field1")
        //b.GetField("field2");
        return  //compare a & b
    }
}

public class MyCollector : Lucene.Net.Search.Collector
{
    CustomQueue _queue = null;
    IndexReader _currentReader;

    public MyCollector(int maxSize)
    {
        _queue = new CustomQueue(maxSize);
    }

    public override bool AcceptsDocsOutOfOrder()
    {
        return true;
    }

    public override void Collect(int doc)
    {
        _queue.InsertWithOverflow(_currentReader.Document(doc));
    }

    public override void SetNextReader(IndexReader reader, int docBase)
    {
        _currentReader = reader;
    }

    public override void SetScorer(Scorer scorer)
    {
    }
}
<小时/>
searcher.Search(query,new MyCollector(10)) //First page.
searcher.Search(query,new MyCollector(20)) //2nd page.
searcher.Search(query,new MyCollector(30)) //3rd page.

编辑@nokturnal

public class MyPriorityQueue<TObj, TComp> : Lucene.Net.Util.PriorityQueue<TObj>
                                where TComp : IComparable<TComp>
{
    Func<TObj, TComp> _KeySelector;

    public MyPriorityQueue(int size, Func<TObj, TComp> keySelector) : base()
    {
        _KeySelector = keySelector;
        Initialize(size);
    }

    public override bool LessThan(TObj a, TObj b)
    {
        return _KeySelector(a).CompareTo(_KeySelector(b)) < 0;
    }

    public IEnumerable<TObj> Items
    {
        get
        {
            int size = Size();
            for (int i = 0; i < size; i++)
                yield return Pop();
        }
    }
}
<小时/>
var pq = new MyPriorityQueue<Document, string>(3, doc => doc.GetField("SomeField").StringValue);
foreach (var item in pq.Items)
{
}

关于lucene - 当我不知道创建时的最大大小时,如何使用 Lucene 的 PriorityQueue?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7936473/

相关文章:

java - Lucene 从索引更新文档字段,没有松散信息

indexing - 如何: Increase Lucene .净索引速度

java - 搜索结果归因于 Hibernate Search 中的字段

azure - Windows Azure Solr和hadoop数据

lucene - 使用 Umbraco Examine 按短语中的确切单词搜索

solr - 使用 Hadoop 进行导入操作并使用 Solr 提供 Web 界面是否有意义?

geolocation - Lucene.net 邻近搜索

java - 如何在Lucene中搜索特定范围内的术语

elasticsearch - 通过Elasticsearch在磁盘上存储在lucene中的原始json文档在哪里(linux-ubuntu)

lucene - pattern_replace 中的不区分大小写的替换