0

在我的应用程序中,我有一个用户表,其中包含first_namelast_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 基于第一个字母,thenSOUNDEX(Cressy)与 不同SOUNDEX(De cressy),即使它们非常相似。
  • 变音位基于字母的位置(以“kn”开头就像以“n”开头,但仅在第一个位置)
  • levenstein 不关心字符串长度:De Cressy 与 Cressy 不同。

您对“混合”这些方法有什么想法,或者您对我有其他想法吗?

4

1 回答 1

0

我强烈建议您尝试使用 Solr 或 Elasticsearch 来满足您的要求(以及更大的灵活性和更好的性能)。

但是,如果您想在 MySQL 中复制一个基本的语音搜索引擎,您需要能够full_name在插入时(以及在自动完成时的每个查询)提取多个标记(单词或单词编码)。

1)。首先,确保您的full_name列是 type FULLTEXT。然后切换到MATCH...AGAINST查询语法代替LIKE %foo%.

这将为您购买精确的内部令牌匹配,例如“de cressy”的“cressy”。

您使用 Levenshtein 距离作为排序标准的想法不错,但是运行起来很昂贵,因此请确保您已经LIMIT编辑了MATCH...AGAINST查询,并且ORDER BY MATCH... DESC如果您要输出levenshtein(query, full_name)作为选择。

目标是避免在所有行上运行levenshtein

2)。如果您仍然有兴趣扩展您的结果以包含类似声音

创建一个带有外键列的phonetic_token表,返回到您的主名称表(这是一个一对多的关系名称到标记)。

将列soundex, 和添加metaphone到此表中。

将记录插入主名称表时,另外在空白处解析它们,并将每个名称单词的 soundex 和 metaphone 编码插入到phonetic_token.

您可能需要添加一些解析逻辑以确保记录所有三倍的名字和三倍的姓氏(例如,在语音编码之前,确保“de cressy”标记为“de”、“cressy”和“decressy”,以便匹配预期的输入。)

现在,当查询要显示的声音相似的名称完成时,您实际上将使用phonetic_tokenWHERE soundex IN(来自查询令牌的 soundex 代码列表)或 metaphone IN(来自查询令牌的 metaphone 代码列表)加入您的主名称表。

MATCH(full_name)...AGAINST(query_text)在产生太少结果的情况下,我建议将此语音匹配作为第二个查询运行。


同样,Solr 或 Elasticsearch 将通过配置为您完成所有这些文本处理,同时为您提供更快速的性能。根据您的应用程序的范围,从 MySQL 中提取文本匹配可能会为您节省大量时间和麻烦。

于 2015-10-20T17:08:03.527 回答