在我的应用程序中,我有一个用户表,first_name
和last_name
。我目前有第三列full_name
(自动生成),如下所示:first_name + last_name + first_name(没有特殊字符)。
"Etienne", "De Crécy", "Etienne De Crecy Etienne"
现在,我有一个简单的算法来自动完成用户输入(删除了特殊字符):
SELECT * FROM users WHERE full_name LIKE "%input%"
此查询返回Etienne,其中包含输入Crécy Etienne
,Etienne De
,Cré
,Cre
,Etienne
我想在此查询中添加一些模糊以允许用户误导。当用户写道时,这个新算法应该能够返回Etienne:
Etiene
(与名字相似)Etienne Crecy
(类似于全名,没有特征)Crecy Etienne
(类似于全名,没有特别的,其他方向)De Cressi
(听起来像姓氏)Cressi
(听起来像姓氏,没有特别之处)我做了很多搜索,最相关的想法是使用SOUNDEX
方法(或Metaphone
程序)或levenstein
程序。我无法使用作为,因为:
SOUNDEX(Cressy)
与SOUNDEX(De cressy)
不同,即使它们非常相似。您对“混合”这些方法有什么想法,或者您对我有任何其他想法吗?
答案 0 :(得分:0)
我强烈建议您尝试使用Solr或Elasticsearch来满足您的要求(以及更高的灵活性和更好的性能)。
但是,如果你想在MySQL中复制一个基本的语音搜索引擎,你需要能够在插入时按full_name
提取多个令牌(单词或单词编码)(以及自动完成时的每个查询)。
1)。首先,确保您的full_name
列的类型为FULLTEXT
。然后切换到MATCH...AGAINST
查询语法代替LIKE %foo%
。
这将为您购买精确的内部令牌匹配,如“de cressy”的“cressy”。
您使用Levenshtein距离作为排序标准的想法并不错,但运行成本很高,因此请确保LIMIT
MATCH...AGAINST
ORDER BY MATCH... DESC
查询和{{1}如果您要输出 levenshtein(query,full_name)作为select的一部分。
目标是避免在所有行上运行 levenshtein
2)。如果您仍然有兴趣扩展结果以包含声音相似:
创建一个 phonetic_token 表,其中一个外键列返回到您的主名称表(它是一对多关系名称到令牌)。
将列soundex
和metaphone
添加到此表中。
将记录插入主名称表时,另外在空白处解析它们,并插入soundex&将每个名字的metaphone编码转换为phonetic_token
。
您可能需要添加一些解析逻辑,以确保记录所有名字三倍和姓氏三倍(例如,在语音编码之前,请确保“de cressy”标记为“de”,“cressy”和“decressy”为了匹配预期的输入。)
现在,在查询要显示的声音完成名称时,您实际上将使用phonetic_token
WHERE soundex IN加入您的主要名称表(查询令牌的soundex代码列表 )或metaphone IN(来自查询令牌的 metaphone代码列表)。
我建议在MATCH(full_name)...AGAINST(query_text)
产生的结果太少的情况下,将此语音匹配作为第二个查询运行。
同样,Solr或Elasticsearch将通过配置为您完成所有这些文本争论,同时为您提供更快捷的性能。根据应用程序的范围,从MySQL中提取文本匹配可能会为您节省大量时间和麻烦。