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

Dea*_*ane 4 lucene lucene.net

我为Lucene.Net构建了一个自定义收集器,但我无法弄清楚如何订购(或页面)结果.每次调用Collect时,我都可以将结果添加到内部PriorityQueue中,我理解这是正确的方法.

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

但是,在收集器中,搜索器在收到新结果时只调用Collect,因此我不知道在创建PriorityQueue时有多少结果.基于此,我无法弄清楚如何使PriorityQueue工作.

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

L.B*_*L.B 6

PriorityQueue不是SortedListSortedDictionary.它是一种排序实现,它返回N个元素的前M个结果(您的PriorityQueue的大小).您可以根据需要添加任意数量的InsertWithOverflow项目,但它只能包含前M个元素.

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

Everytime Commit gets called, I can add the result to an internal 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)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)
searcher.Search(query,new MyCollector(10)) //First page.
searcher.Search(query,new MyCollector(20)) //2nd page.
searcher.Search(query,new MyCollector(30)) //3rd page.
Run Code Online (Sandbox Code Playgroud)

编辑@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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
var pq = new MyPriorityQueue<Document, string>(3, doc => doc.GetField("SomeField").StringValue);
foreach (var item in pq.Items)
{
}
Run Code Online (Sandbox Code Playgroud)