一尘不染

MySQL混合Damerau–Levenshtein Fuzzy与Like通配符

algorithm

我最近在MySQL中实现了Damerau-Levenshtein算法的UDF,并想知道是否有办法将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语句在隔离中工作良好,但不适用于单个单词。我将不得不将上述SQL更改为…

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

…这当然只返回ID2。如果希望所有返回的单词中包含“文档”或它的变体的记录都出现在“文本”字段中,我希望有一种将模糊和通配符组合在一起的方法。


阅读 263

收藏
2020-07-28

共1个答案

一尘不染

在使用人名并对其进行模糊查找时,对我来说有效的是创建第二个单词表。还创建第三个表,该表是一个相交表,用于包含文本的表和单词表之间的多对多关系。将一行添加到文本表后,您将文本拆分为多个单词并适当地填充了相交表,并在需要时向单词表中添加了新单词。一旦建立了这种结构,您就可以更快地进行查找,因为您只需要对唯一单词表执行damlev函数。一个简单的联接将为您提供包含匹配单词的文本。
在此处输入图片说明

查询单个单词匹配将如下所示:

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上相匹配的相交行进行分组并对匹配数进行排名来对结果进行排名。

2020-07-28