Как я могу использовать PriorityQueue Lucene, когда я не знаю максимального размера во время создания? - PullRequest
4 голосов
/ 29 октября 2011

Я создал собственный коллектор для Lucene.Net, но не могу понять, как упорядочить (или создать страницу) результаты.Каждый раз, когда вызывается Collect, я могу добавить результат во внутренний PriorityQueue, который, как я понимаю, является правильным способом сделать это.

Я расширил PriorityQueue, но при создании требуется параметр размера.Вы должны вызвать Initialize в конструкторе и передать максимальный размер.

Однако в сборщике искатель просто вызывает Collect, когда получает новый результат, поэтому Я не знаю, сколькоРезультаты, которые я получаю при создании PriorityQueue .Исходя из этого, я не могу понять, как заставить работать PriorityQueue.

Я понимаю, что, возможно, здесь не хватает чего-то простого ...

Ответы [ 2 ]

6 голосов
/ 29 октября 2011

PriorityQueue не является SortedList или SortedDictionary.Это своего рода реализация сортировки, где она возвращает лучшие результаты M (размер вашего PriorityQueue) из N элементов.Вы можете добавить InsertWithOverflow столько элементов, сколько хотите, но в нем будут содержаться только самые верхние элементы M.

Предположим, ваш поиск дал 1000000 просмотров.Вы бы вернули все результаты пользователю?Лучшим способом было бы вернуть первые 10 элементов пользователю (используя PriorityQueue(10)), и если пользователь запрашивает следующие 10 результатов, вы можете выполнить новый поиск с помощью PriorityQueue(20) и вернуть следующие 10 элементы и так далее.Это хитрость, которую использует большинство поисковых систем, подобных Google.

Everytime Commit gets called, I can add the result to an internal PriorityQueue.

Я не могу понять отношения между Commit и search, поэтому я добавлю пример использования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)
{
}
0 голосов
/ 29 октября 2011

Причина, по которой приоритетная очередь Lucene ограничена по размеру, заключается в том, что она использует реализацию фиксированного размера, которая очень быстра.

Подумайте, каково разумное максимальное количество результатов, которые можно получить за раз, и используйте это число«растрата», когда результатов мало, не так уж плоха для выгоды, которую она получает.

С другой стороны, если у вас есть такое огромное количество результатов, что вы не можете их удержать, то каквы собираетесь их обслуживать / показывать?Имейте в виду, что это относится к "лучшим" попаданиям, так что, перебирая результаты, вы все равно будете попадать все реже и реже.

...