我想知道Apache Lucene使用的字符串匹配算法。我一直在浏览由here给出的lucene使用的索引文件格式。似乎lucene存储文本中出现的所有单词,以及每个文档中出现的频率。 但据我所知,对于有效的字符串匹配,它需要预处理文档中出现的单词。
例如: 搜索“iamrohitbanga是stackoverflow的用户”(使用模糊匹配)
在某些文件中。
可能有一个包含字符串“rohit banga”
的文档发现搜索字符串中存在子字符串rohit和banga,它会使用一些有效的子字符串匹配。
我想知道它是哪种算法。如果它做了一些预处理,java api中的函数调用会触发它。
答案 0 :(得分:6)
正如Yuval解释的那样,一般来说,Lucene适合完全匹配(通过在索引和查询时使用分析器对术语进行规范化)。
在Lucene主干代码中(尚未发布任何版本)实际上对于不正确的匹配(例如Regex,Wildcard和Fuzzy)存在后缀树使用。
这种方式的工作方式是Lucene术语词典本身实际上是后缀树的一种形式。您可以在几个地方提到的文件格式中看到这一点:
因此,如果前一个术语的文本是“骨骼”而术语是“boy”,则PrefixLength为2,后缀为“y”。
术语info索引通过以特定间隔(默认情况下每128个术语)索引此树为我们提供“随机访问”。
如此低级别它是一个后缀树,但在更高级别,我们利用这些属性(主要是在IndexReader.terms中指定的属性将术语字典视为确定性有限状态自动机(DFA):
返回从给定术语开始的所有术语的枚举。如果给定的术语不存在,则枚举位于第一个术语大于提供的术语。枚举由Term.compareTo()排序。每个术语都大于枚举中它前面的所有术语。
Regex,Wildcard和Fuzzy等不精确的查询本身也被定义为DFA,“匹配”只是DFA交集。
答案 1 :(得分:2)
Lucene的基本设计使用精确的字符串匹配,或使用Analyzer定义等效的字符串。分析器将文本分解为可索引的标记。在此过程中,它可以整理等效的字符串(例如大写和小写,词干串,删除变音符号等) 生成的标记作为字典存储在索引中,加上文档中标记的发布列表。因此,您可以构建和使用Lucene索引,而无需使用字符串匹配算法(如KMP)。 但是,FuzzyQuery和WildCardQuery使用类似的内容,首先搜索匹配的字词,然后使用它们进行完全匹配。有关解决此问题的新方法,请参阅Robert Muir's Blog Post about AutomatonQuery。
答案 2 :(得分:0)
正如您所指出的,Lucene只存储文档中出现的术语列表。 Lucene如何提取这些词语取决于你。默认的lucene分析器简单地打破由空格分隔的单词。您可以编写自己的实现,例如源字符串'iamrohitbanga'产生5个令牌:'iamrohitbanga','我','am','rohit','banga'。
请查看TokenFilter类的lucene API文档。