【发布时间】:2016-11-01 18:29:24
【问题描述】:
我使用 Lucene.Net 在 C# 中创建了一个搜索/浏览应用程序的原型。源数据是一个中等大小的 5MB XML 文件(包含大约 900 个“文档”),我使用 Lucene 对其进行索引。我的搜索工作正常并且速度非常快。对于这个应用程序,浏览和查看每个“命中”文档很重要,因此用户可以选择一个命中并查看该文档的完整视图(通常适合一半屏幕),我需要在其中突出显示的匹配搜索词看法。我正在使用 WPF 和 MVVM 方法。文档视图目前使用大约十二个 ContentControl 实现,其中六个用于显示使用 highlightConverter 的可搜索字段。
性能很差,所以我添加了秒表计时来隔离问题。我模型中的 HighlightSearchTerms 方法似乎是罪魁祸首(大约需要 100-600 毫秒来执行)。如果我将此方法短路以仅返回输入文本,则性能很好。
方法如下:
_analyzer is a StandardAnalyzer(_luceneVersion)
_parser is a QueryParser(_luceneVersion, “content”, _analyzer)
_formatter is a SimpleHTMLFormatter(“|~S~|”, “|~E~|”);
private string HighlightSearchTerms(string text, string queryString)
{
var query = new BooleanQuery();
query.Add(_parser.Parse(queryString), Occur.SHOULD);
var fragmentScorer = new QueryScorer(query);
var highlighter = new Highlighter(_formatter, fragmentScorer);
highlighter.TextFragmenter = new NullFragmenter();
var tokenStream = _analyzer.TokenStream(null, new StringReader(text));
string highlightedText = highlighter.GetBestFragment(tokenStream, text);
return highlightedText == null ? text : highlightedText;
}
几年前,我阅读了“Lucene In Action”一书,并再次翻阅了相关部分,看看我是否能得到任何想法。我也在网上搜索了很多。因此,这里有几个问题或可能探索的领域。
- 我可以忽略评分吗?我不需要显示匹配的上下文 搜索词,所以我不需要将命中文档分解成 碎片并获得各种碎片的“分数”。我想要 按标题显示的命中列表,然后当用户选择一个命中时, 整个命中文档突出显示。我知道怎么做 使用 NullFragmenter 和 GetBestFragment,但我不知道是否 使评分操作短路。会省略计分 提高性能?
- 我已经考虑重构我的视图以使用单个小部件 将命中文档显示为一个 HTML 或 RTF 文本块。那样, 我只能调用一次 highlight 方法而不是 10 或 15 次(一些 ContentControls 在 ItemsControl 内,所以有 视图上某些字段的多个实例)。我希望这会 显着提升性能。突出显示将在文本上 用表格格式等标记,但我想 那还能用吗?
- 我还缺少什么使我的突出显示方法 太慢了?半秒似乎太慢了——好像我真的搞砸了一些基本的东西。
【问题讨论】:
-
我已经进行了选项 2,它工作正常。我担心标记的 HTML 字符串由于标记而无法正确突出显示,并且因为 Lucene 文档强调传递给荧光笔的内容应该与最初索引的内容完全匹配。但我想这些文档只是提醒您确保您的索引是最新的。我会保持这个问题的开放性,因为我觉得这是一种解决方法而不是解决方案。
标签: performance lucene lucene.net lucene-highlighter