【问题标题】:Lucene Hightlighter sometimes inexplicably returns blank fragmentsLucene Hightlighter 有时会莫名其妙地返回空白片段
【发布时间】:2015-05-17 05:35:11
【问题描述】:

过去几天我一直在开发一个 Lucene 文档搜索程序,到目前为止一切都进展顺利。我正在尝试使用Lucene.Net.Highlight.Highlighter 类为我的搜索结果显示相关的sn-ps,但它无法始终如一地工作。 大多数情况调用Highlighter.GetBestFragments() 完全符合我的预期(显示带有给定查询字符串的相关文本 sn-ps),但有时它只返回一个空字符串。

我已经三次检查了我的输入,我可以验证我正在使用的查询字符串是否存在于输入文本中,但是荧光笔有时只是任意返回一个空字符串。问题是可重现的;使用相同查询时,返回空白片段的文档将继续返回空白片段,而具有合法片段的文档继续具有合法片段。

但是,问题不是特定于文档的。某些查询为文档返回有效片段,而其他查询为同一文档返回空字符串。该问题似乎也与我的分析仪无关;无论我使用StandardAnalyzer 还是SnowballAnalyzer,都会出现问题。

经过数小时的探索,我无法在失败的查询/文档中找到任何模式与有效的模式。请记住,这发生在使用完全相同的查询专门从 Lucene 索引中拉回的文档上。这意味着Searcher 能够在目标文档中找到相关的查询字符串,但Highlighter 不能。

这是 Lucene 中的错误吗?如果是这样,我该如何解决?

我的代码:

private static SimpleHTMLFormatter _formatter = new SimpleHTMLFormatter("<b>", "</b>");
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<DVDoc> 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 类,没有魔法。)

而且由于每个人都喜欢示例输入和输出:

我使用的是 Lucene.NET 2.9.4g 版。

【问题讨论】:

  • 您是否尝试过修改 MaxDocCharsToAnalyze 值? lucene.apache.org/core/old_versioned_docs/versions/2_9_2/api/…
  • @JfBeaulac 太棒了!这立即解决了这个问题。我不知道为什么我从未在文档中注意到该功能,我一定是直接跳过了它。无论如何,请写下您的评论作为答案,我很乐意接受。

标签: c# lucene.net


【解决方案1】:

默认情况下,荧光笔只会处理文档的前 51200 个字符。

要增加此限制,请设置 MaxDocCharsToAnalyze 属性。

http://lucene.apache.org/core/old_versioned_docs/versions/2_9_2/api/contrib-highlighter/org/apache/lucene/search/highlight/Highlighter.html#setMaxDocCharsToAnalyze(int)

【讨论】:

  • 出于好奇,如果我有非常大的文档要分析,有人能告诉我最好的方法是什么吗?我猜 MaxDocCharsToAnalyze 属性可以设置为 Int32.MaxValue,目前为 2147483647。如果我需要分析的文本不止于此,会发生什么?
猜你喜欢
  • 1970-01-01
  • 2013-08-02
  • 2012-03-12
  • 2022-11-23
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 2014-06-30
  • 1970-01-01
相关资源
最近更新 更多