Lucene Hightlighter иногда по необъяснимым причинам возвращает пустые фрагменты.

Последние несколько дней я работал над программой поиска документов Lucene, и до сих пор все шло хорошо. Я пытаюсь использовать класс Lucene.Net.Highlight.Highlighter, чтобы показать релевантные фрагменты для моих результатов поиска, но он не работает последовательно. В большинствеслучаев вызов Highlighter.GetBestFragments()делает именно то, что я ожидал (показывает соответствующие текстовые фрагменты с заданной строкой запроса в них), но иногда он просто возвращает пустой строки.

Я трижды проверил свои входные данные и могу убедиться, что строка запроса, которую я использую, существует во входном тексте, но средство выделения иногда произвольно возвращает пустую строку. Проблема воспроизводима; документы, которые возвращают пустые фрагменты, будут по-прежнему возвращать пустые фрагменты при использовании того же запроса, в то время как документы, которые имеют допустимые фрагменты, продолжают иметь допустимые фрагменты.

Однако проблема НЕ связана с конкретным документом. Некоторые запросы возвращают допустимые фрагменты для документа, в то время как другие запросы возвращают пустую строку для того же документа. Проблема также не связана с моим анализатором; проблема проявляется независимо от того, использую ли я StandardAnalyzerили SnowballAnalyzer.

После многих часов ковыряния я не смог найти какой-либо закономерности в запросах/документах, которые терпят неудачу по сравнению с теми, которые работают. Имейте в виду, что это происходит с документами, которые были специально извлечены из индекса Lucene с использованием точно такого же запроса. Это означает, что Searcherможет найти соответствующую строку запроса в целевом документе, а Highlighter— нет.

Является ли это ошибкой Lucene? Если да, то как я могу обойти это?

Мой код:

private static SimpleHTMLFormatter _formatter = new SimpleHTMLFormatter("", "");
private static SimpleFragmenter _fragmenter = new SimpleFragmenter(50);
...
{
    using (var searcher = new IndexSearcher(analyzerInfo.Directory, false))
    {
        QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "Text", analyzerInfo.Analyzer);
        parser.SetMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);

        //build query
        BooleanQuery booleanQuery = new BooleanQuery();
        booleanQuery.Add(new TermQuery(new Term("PageNum", "0")), BooleanClause.Occur.MUST);
        booleanQuery.Add(parser.Parse(searchQuery), BooleanClause.Occur.MUST);
        Query query = booleanQuery.Rewrite(searcher.GetIndexReader());

        //get results from query
        ScoreDoc[] hits = searcher.Search(query, 50).ScoreDocs;
        List results = hits.Select(hit => MapLuceneDocumentToData(searcher.Doc(hit.Doc))).ToList();

        //add relevant fragments to search results (shows WHY a certain result was chosen)
        QueryScorer scorer = new QueryScorer(query);
        Highlighter highlighter = new Highlighter(_formatter, scorer);
        highlighter.SetTextFragmenter(_fragmenter);
        foreach (DVDoc result in results)
        {
            TokenStream stream = analyzerInfo.Analyzer.TokenStream("Text", new StringReader(result.Text));
            result.RelevantFragments = highlighter.GetBestFragments(stream, result.Text, 3, "...");
        }

        //clean up
        analyzerInfo.Analyzer.Close();
        searcher.Close();

        return results;
    }
}

(Примечание: DVDoc— это просто структура, в которой хранится информация о найденных документах. Метод MapLuceneDocumentToDataпревращает Lucene Documentв мой пользовательский класс DVDoc, никакого волшебства в этом нет.)

А так как всем нравятся примеры ввода и вывода:

I Я использую Lucene.NET версии 2.9.4g.

6
задан ean5533 23 May 2012 в 19:03
поделиться