是否最好使用lucene KeywordAnalyzer为自动建议文本框索引文本?

时间:2013-12-20 19:17:06

标签: lucene.net lucene

我在搜索表单中有一个文本框,我想附加一个组合框/自动完成小部件。在用户输入时,我想自动建议相关的地名。因此,如果用户输入“Ca”,建议柬埔寨,喀麦隆,加拿大,佛得角等,排名高于北卡罗来纳州和南卡罗来纳州。如果用户输入“海”,返回红海,黑海等物品,但也许不是切尔西(如果有的话,应该得分较低)。我们的地名数据库非常精细和复杂,有很多数据和很多地方的替代名称/翻译。数据存储在SQL Server中,我们使用Entity Framework作为数据访问层。不用说,使用LINQ to Entities有效地查询我们的Places实体聚合是缓慢且低效的。

我正在研究Lucene.Net,而不是雕刻自定义SQL和索引以优化数据库搜索。今天是我测试它的第一天。我阅读的大部分Lucene帮助使用StandardAnalyzer来编制索引。我在几次测试中使用它时遇到了一些麻烦。例如,请考虑以下事项:

var searchTerms = new[] { "Ca", "China", "Sea", };
searchTerms = searchTerms.Concat(searchTerms.Select(x => x.ToLower())).ToArray();
var reader = IndexReader.Open(_directory, true);
foreach (var searchTerm in searchTerms)
{
    var searcher = new IndexSearcher(reader);
    var query1 = new WildcardQuery(new Term("OfficialName", string.Format("*{0}*", searchTerm)));
    var query2 = new TermQuery(new Term("OfficialName", searchTerm));
    var query3 = new QueryParser(Version.LUCENE_30, "OfficialName", new SimpleAnalyzer()).Parse(searchTerm);
    var query4 = new PrefixQuery(new Term("OfficalName", searchTerm));
    var query5 = new BooleanQuery();
    query5.Add(query1, Occur.SHOULD);
    query5.Add(query2, Occur.SHOULD);
    query5.Add(query3, Occur.SHOULD);
    query5.Add(query4, Occur.SHOULD);
    var queryToRun = query5;
    var results = searcher.Search(queryToRun, int.MaxValue);
    var hits = results.ScoreDocs;

上面的代码只是尝试了正常和较低版本的术语。有趣的是,“Ca”查询没有返回任何结果,但“ca”返回了大量的结果 - 非洲,北美等。我想我在某处读到标准分析器根据案例区分术语,所以这可能是为什么.. ?其他搜索字词会返回人们可能期望的内容。

使用关键字分析器对相同数据进行索引时,结果会有很大差异。一个奇怪的事情是“中国”只返回1个结果,“Uchinada-machi”。我本以为它也会回归“中国”和“东海”。此外,“海洋”的结果如“肯辛顿和切尔西皇家自治市”和“斯旺西市和县”,但没有其他预期结果。

那我该怎么办呢?我应该为不同的分析仪提供不同的文本索引吗?我是否需要查询带有小写文本的文档字段?我读到了使用NGram标记器,但它们似乎不再出现在Lucene.Net.Analysis命名空间中。

1 个答案:

答案 0 :(得分:6)

我认为这个问题的答案是“这取决于,但可能不是。”根据{{​​3}},KeywordAnalyzer将整个string视为单个分析令牌。所以它不会将像“东海”这样的东西分解成“东方”,“中国”和“海洋”代币来分别搜索它们。知道了这一点,我得到了上述结果,我尝试了各种查询。

我对Lucene对案例敏感性的理解仍然没有完全自信,所以如果我错了请纠正我,但似乎你必须将搜索输入套管与用于索引的字段和分析器相匹配。我真正掌握这一点的唯一方法是测试分析器的不同组合,文档字段(正常和低级)以及字段设置(ANALYZEDNOT_ANALYZED)。上面引用的链接指的是将文本小写为规范化的过程。

我发现,当使用StandardAnalyzer分析搜索的字段时,使用大写和小写输入文本(如“Ch”)的组合搜索没有返回任何结果。现在我已经阅读了上面的链接,这更有意义。在创建搜索令牌时,似乎StandardAnalyzer会标准化为小写。因此,如果您执行new QueryParser(Version.LUCENE_30, field, analyzer).Parse("Ch")之类的操作,大多数分析器实际上会将其转换为小写,因为索引中的标记是小写的。

对于OP,似乎一个好的解决方案是规范化(小写)用户对针对由分析器规范化的字段运行的查询的输入。如果需要,您可以将结果与针对NOT_ANALYZED字段(或使用非规范化分析器索引的字段)的非规范化用户输入结合起来(可能为后者提供更高的提升因子)。