Lucene Hightlighter有时会莫名其妙地返回空白片段
本文关键字:返回 空白 片段 莫名其妙 Hightlighter Lucene | 更新日期: 2023-09-27 18:35:04
在过去的几天里,我一直在开发Lucene文档搜索程序,到目前为止,一切都进展顺利。我正在尝试使用 Lucene.Net.Highlight.Highlighter
类来显示搜索结果的相关片段,但它无法始终如一地工作。大多数情况下,调用Highlighter.GetBestFragments()
完全符合我的预期(显示具有给定查询字符串的相关文本片段(,但有时它只返回一个空字符串。
我已经三次检查了我的输入,我可以验证我使用的查询字符串是否存在于输入文本中,但荧光笔有时会任意返回一个空字符串。该问题是可重现的;返回空白片段的文档在使用相同的查询时将继续返回空白片段,而具有合法片段的文档将继续具有合法片段。
但是,该问题不是特定于文档的。某些查询返回文档的有效片段,而其他查询返回同一文档的空字符串。该问题似乎也与我的分析仪无关;无论我使用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
类,那里没有魔法。
由于每个人都喜欢示例输入和输出:
- GetBestFragments 工作示例
- GetBestFragments不起作用的示例
我使用的是 Lucene.NET 版本2.9.4g。
默认情况下,荧光笔将仅处理文档的前 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(