4

我想知道 Apache Lucene 使用的字符串匹配算法。我一直在浏览这里给出的 lucene 使用的索引文件格式。似乎 lucene 存储文本中出现的所有单词,就像它们在每个文档中出现的频率一样。但据我所知,为了有效的字符串匹配,它需要预处理文档中出现的单词。

示例:搜索“iamrohitbanga 是 stackoverflow 的用户”(使用模糊匹配)

在一些文件中。

可能存在包含字符串“rohit banga”的文档

要发现搜索字符串中存在子字符串 rohit 和 Banga,它将使用一些有效的子字符串匹配。

我想知道它是哪种算法。如果它做了一些预处理,java api中的哪个函数调用会触发它。

4

3 回答 3

6

正如 Yuval 解释的那样,通常 Lucene 是针对精确匹配的(通过在索引和查询时使用分析器对术语进行规范化)。

在 Lucene 主干代码(尚未发布任何版本)中,实际上存在用于不精确匹配的后缀树,例如 Regex、Wildcard 和 Fuzzy。

其工作方式是 Lucene 术语字典本身实际上是一种后缀树形式。您可以在几个地方提到的文件格式中看到这一点:

因此,如果前一个词条的文本是“bone”并且词条是“boy”,那么 PrefixLength 是 2 并且后缀是“y”。

术语信息索引通过以特定间隔(默认情况下每 128 个术语)对该树进行索引,为我们提供“随机访问”。

所以低级它是一个后缀树,但在更高级别,我们利用这些属性(主要是在 IndexReader.terms 中指定的那些将术语字典视为确定性有限状态自动机(DFA):

返回从给定术语开始的所有术语的枚举。如果给定的项不存在,则枚举位于比提供的项大的第一项。枚举按 Term.compareTo() 排序。每个项都大于枚举中它之前的所有项。

Regex、Wildcard、Fuzzy等不精确查询本身也被定义为DFA,而“匹配”就是简单的DFA交集。

于 2010-04-29T13:02:30.977 回答
2

Lucene 的基本设计使用精确的字符串匹配,或者使用Analyzer定义等效的字符串。分析器将文本分解为可索引的标记。在此过程中,它可能会整理等效的字符串(例如,大小写、词干字符串、删除变音符号等)。结果标记作为字典和文档中标记的发布列表存储在索引中。因此,您可以构建和使用 Lucene 索引,而无需使用 KMP 等字符串匹配算法。但是,FuzzyQueryWildCardQuery使用类似的东西,首先搜索匹配项,然后使用它们进行完全匹配。请参阅Robert Muir 的关于 AutomatonQuery 的博客文章,了解解决此问题的新方法。

于 2010-02-07T21:33:06.640 回答
0

正如您指出的那样,Lucene 仅存储文档中出现的术语列表。Lucene 如何提取这些单词取决于您。默认的 lucene 分析器只是简单地破坏由空格分隔的单词。您可以编写自己的实现,例如源字符串“iamrohitbanga”产生 5 个标记:“iamrohitbanga”、“i”、“am”、“rohit”、“banga”。

请查看 TokenFilter 类的 lucene API 文档。

于 2010-02-05T17:14:48.927 回答