Лучший подход найти позицию в результатах поиска Lucene - PullRequest
1 голос
/ 10 февраля 2012

Я использую Lucene.NET и могу искать результаты попаданий как ScoreDoc [].

Мне нужно знать конкретную позицию предмета в ScoreDoc [].Все элементы в ScoreDoc [] являются уникальными.

Пример кода: luceneSearcher.Search (запрос, сборщик);ScoreDoc [] scores = collector.TopDocs (). ScoreDocs

Например, мне нужно найти позицию элемента поиска в ScoreDoc [], у которого есть свойство пользовательского идентификатора, значение которого может быть равно 99999.

Я могу перебрать элемент в показателях [] и проверить свойство идентификатора, которое соответствует '99999', затем вернуть позицию, но это может привести к снижению производительности, потому что результаты [] могут иметь тысячи элементов.

Есть ли лучшая техника?

Спасибо

1 Ответ

0 голосов
/ 10 февраля 2012

Я придумал создать новый ExtendedCollector, в котором хранятся CollectedDocuments.

    public class ExtendedCollector : Collector
    {
        private Scorer _scorer;
        private Int32 _docBase;
        private List<CollectedDocument> _documents;

        public ExtendedCollector()
        {
            _documents = new List<CollectedDocument>();
        }

        public override void SetScorer(Scorer scorer)
        {
            _scorer = scorer;
        }

        public override void Collect(int doc)
        {
            var docId = _docBase + doc;
            var score = _scorer.Score();

            var currentDoc = _documents.FirstOrDefault(d => d.DocId == docId);

            if (currentDoc == null)
                _documents.Add(new CollectedDocument()
                                   {DocId = docId, Score = score, OriginalIndex = _documents.Count, Index = _documents.Count});
            else
                currentDoc.Score = score;
        }

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

        public override bool AcceptsDocsOutOfOrder()
        {
            return false;
        }

        public List<CollectedDocument> Documents
        {
            get { return _documents; }
        }

        public List<CollectedDocument> DocumentsByScore
        {
            get
            {
                var result = _documents.OrderByDescending(d => d.Score).ToList();
                var itemId = 0;
                foreach (var collectedDocument in result)
                {
                    itemId++;
                    collectedDocument.Index = itemId;
                }

                return result;
            }
        }
    }

CollectedDocument выглядит следующим образом

    public class CollectedDocument
    {
        public Int32 DocId { get; set; }
        public float Score { get; set; }
        public int OriginalIndex { get; set; }
        public int Index { get; set; }
    }

Всякий раз, когда вы хотите получить результаты, вы делаете

        var myCollector = new ExtendedCollector();
        searcher.Search(searchQuery, myCollector);

        foreach (var doc in myCollector.Documents)
        {
            var docIndex = doc.Index; //this is the current index in a list
            var originalIndex = doc.OriginalIndex; //this is item Id set when doc was collected
        }

Вы также можете получить документы, упорядоченные по счету, используя

myCollector.DocumentsByScore

Возможно, это не самое простое решение, но оно работает.Если у кого-то есть лучшее решение, пожалуйста, опубликуйте его, так как я бы тоже хотел это знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...