我试图找到一种方法,使用levenshtein方法将一些模糊搜索方法应用到我们的店面搜索字段中,但是我遇到了一个问题,即如何只搜索部分产品名称。
例如,客户搜索 scisors
但我们有一种产品叫 electric scissor
. 使用levenshtein方法 levenshtein("scisors","electric scissor")
我们将得到11的结果,因为电气部分将被算作一个差值。
我要寻找的是一种方法,它可以查看产品名称的子字符串,这样就可以将它与 levenshtein("scisors","electric")
然后还有 levenshtein("scisors","scissor")
我们可以在第二个子串中得到一个只有2的结果,从而将这个结果作为搜索结果的一部分显示出来。
不起作用的例子让你知道我在追求什么:
SELECT * FROM products p WHERE levenshtein("scisors", p.name) < 5
问题:有没有一种方法可以编写一个sql语句来检查字符串的各个部分?我是否需要在我的数据库中创建更多的函数来处理它或者修改我现有的函数,如果需要,它会是什么样子?
我目前正在使用levenshtein方法的这个实现:
//levenshtein(s1 as VARCHAR(255), s2 as VARCHAR(255))
//returns int
BEGIN
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
DECLARE s1_char CHAR;
-- max strlen=255
DECLARE cv0, cv1 VARBINARY(256);
SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0;
IF s1 = s2 THEN
RETURN 0;
ELSEIF s1_len = 0 THEN
RETURN s2_len;
ELSEIF s2_len = 0 THEN
RETURN s1_len;
ELSE
WHILE j <= s2_len DO
SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1;
END WHILE;
WHILE i <= s1_len DO
SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1;
WHILE j <= s2_len DO
SET c = c + 1;
IF s1_char = SUBSTRING(s2, j, 1) THEN
SET cost = 0; ELSE SET cost = 1;
END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost;
IF c > c_temp THEN SET c = c_temp; END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
IF c > c_temp THEN
SET c = c_temp;
END IF;
SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
END WHILE;
SET cv1 = cv0, i = i + 1;
END WHILE;
END IF;
RETURN c;
END
1条答案
按热度按时间pod7payv1#
这是一个有点长的评论。
首先,我建议使用带有同义词列表的全文搜索。也就是说,您可能有拼写能力非常差的用户,因此同义词列表可能很难维护。
如果你用levenshtein距离,那么我建议你按单词来做。对于用户输入的每个单词,计算
name
现场。然后把这些加在一起得到最佳匹配。在您的示例中,您可以进行以下比较:
levenshtein('剪刀','电')
levenshtein('剪刀','剪刀')
最小值是第二个。如果用户键入多个单词,例如
'electrk scisors'
,那么你会做什么levenshtein('electrk','electric')<--最小值
levenshtein('electrk','scissor')
levenshtein('剪刀','电')
levenshtein('剪刀','剪刀')<--最小值
这可能是一种直观的搜索方法。