在索引中搜索作为搜索词前缀的术语,反之亦然(!)

时间:2012-11-15 08:55:36

标签: java lucene

如果我搜索“bahnhofstrasse”,我希望Lucene找到一个包含术语“bahnhofstr”的文档,即我不仅希望查找包含我的搜索词是前缀的条款的文档,还要查找文档包含本身就是我的搜索词的前缀的术语...

我该怎么做?

2 个答案:

答案 0 :(得分:1)

如果我理解正确,并且您的搜索字符串是一个确切的字符串,您可以在Lucene中设置queryParser.setAllowLeadingWildcard(true);以允许进行通配符搜索(这可能会也可能不会很慢 - 我已经合理地看到了它们快速,但在只有60,000多个Lucene文档的情况下)。

您的示例查询语法可能类似于:

*bahnhofstr bahnhofstr*

或可能(尚未测试过)只是:

*bahnhofstr*

答案 1 :(得分:0)

我认为模糊查询可能对您最有帮助。这将根据您查询中的Levenshtein距离对条款进行评分。如果没有指定最小相似度,它将有效地匹配每个可用术语。这可以使它低于高性能,但确实能达到你想要的效果。

模糊查询由〜字符表示,例如:

firstname:bahnhofstr~

或者具有最小相似度(0到1之间的数字,0是最宽松的,没有最小值)

firstname:bahnhofstr~0.4

或者,如果您要构建自己的查询,请使用FuzzyQuery

这并不完全符合您的要求,但却是最简单的接近方式。

至于你正在寻找什么,我不知道一个简单的Lucene调用来实现它。我可能只是将该术语拆分为一系列术语查询,您可以在查询字符串中表示如下:

firstname:b
firstname:ba
firstname:bah
firstname:bahn
firstname:bahnh
firstname:bahnho
firstname:bahnhof
firstname:bahnhofs
firstname:bahnhofst
firstname:bahnhofstr*

顺便说一下,我自己实际上不会为它生成一个查询字符串。我自己构建了TermQuery和PrefixQuery对象。

得分会有点扭曲,我可能会更长时间地提高更长的查询以获得更好的排序,但这是我想到的方法,可以很容易地完成你正在寻找的东西。 DisjunctionMaxQuery可以帮助您使用其他术语,并获得更合理的评分。

希望模糊查询适合你。似乎是一个更好的解决方案。

另一种选择,如果你有很多需要这种性质的查询,可能在索引时将字段标记为n-gram(参见NGramTokenizer),这将允许你有效地使用{{ 3}}以达到你想要的结果。