MySQL混合Damerau-Levenshtein模糊与喜欢通配符

时间:2013-01-10 15:40:00

标签: mysql algorithm levenshtein-distance

我最近将Damerau-Levenshtein算法的UDF实现到MySQL中,并且想知道是否有办法将Damerau-Levenshtein算法的模糊匹配与Like函数的通配符搜索结合起来?如果我在表格中有以下数据:

ID | Text
---------------------------------------------
1  | let's find this document
2  | let's find this docment
3  | When the book is closed
4  | The dcument is locked

我想运行一个包含Damerau-Levenshtein算法的查询......

select text from table where damlev('Document',tablename.text) <= 5;

...使用通配符匹配在我的查询中返回ID 1,2和4。我不确定语法或是否可行,或者我是否必须采用不同的方法。上面的select语句在issolation中工作正常,但不适用于单个单词。我必须将上面的SQL更改为...

select text from table where 
 damlev('let's find this document',tablename.text) <= 5;

...当然只返回ID 2.我希望有一种方法可以将模糊和通配符组合在一起,如果我想要返回的所有记录都有“文档”或其中的变体出现在文字字段。

1 个答案:

答案 0 :(得分:3)

在处理人名并对其进行模糊查找时,对我有用的是创建第二个单词表。还要创建第三个表,该表是包含文本的表与单词表之间的多对多关系的交叉表。将行添加到文本表时,将文本拆分为单词并相应地填充交叉表,并在需要时向单词表添加新单词。一旦这个结构到位,你可以更快地进行查找,因为你只需要在独特单词表上执行你的damlev函数。一个简单的连接可以获得包含匹配单词的文本。 enter image description here

单个字匹配的查询看起来像这样:

SELECT T.* FROM Words AS W
JOIN Intersect AS I ON I.WordId = W.WordId
JOIN Text AS T ON T.TextId = I.TextId
WHERE damlev('document',W.Word) <= 5 

并且两个单词看起来像这样(在我的头顶,所以可能不完全正确):

SELECT T.* FROM Text AS T
JOIN (SELECT I.TextId, COUNT(I.WordId) AS MatchCount FROM Word AS W
      JOIN Intersect AS I ON I.WordId = W.WordId
      WHERE damlev('john',W.Word) <= 2
            OR damlev('smith',W.Word) <=2
      GROUP BY I.TextId) AS Matches ON Matches.TextId = T.TextId
          AND Matches.MatchCount = 2

这里的优点是以一些数据库空间为代价,你只需要将时间昂贵的damlev函数应用于独特的单词,这些单词的数量可能只有十万分之一,而不管表的大小如何的文字。这很重要,因为damlev UDF不会使用索引 - 它会扫描应用它的整个表来计算每一行的值。只扫描独特的单词应该快得多。另一个优点是damlev应用于单词级别,这似乎是你要求的。另一个优点是您可以扩展查询以支持搜索多个单词,并可以通过对TextId上的匹配交叉行进行分组以及对匹配计数进行排名来对结果进行排名。