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

dan*_*wig 2 lucene lucene.net

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

我正在研究Lucene.Net,而不是雕刻自定义SQL和索引以优化数据库搜索.今天是我测试它的第一天.大多数Lucene帮助我读过使用a 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;
Run Code Online (Sandbox Code Playgroud)

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

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

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

dan*_*wig 6

我认为这个问题的答案是"这取决于,但可能不是." 根据Lucene in Action的说法,KeywordAnalyzer将整个string视为单一的分析标记.所以它不会将像"东海"这样的东西分解成"东方","中国"和"海洋"代币来分别搜索它们.知道了这一点,我得到了上述结果,我尝试了各种查询.

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

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

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