如何将 MYSQL 中的公司名称与 PHP 进行模糊匹配以实现自动完成?
-
21-08-2019 - |
题
我的用户将通过剪切和粘贴导入包含公司名称的大字符串。
我有一个现有且不断增长的公司名称 MYSQL 数据库,每个数据库都有一个唯一的 company_id。
我希望能够解析字符串并为每个用户输入的公司名称分配一个模糊匹配。
现在,仅仅进行直接的字符串匹配也很慢。** Soundex 索引会更快吗?如何在用户打字时为他们提供一些选项?**
例如,有人写道:
Microsoft -> Microsoft Bare Essentials -> Bare Escentuals Polycom, Inc. -> Polycom
我发现以下线程似乎与此问题类似,但发布者尚未批准,我不确定他们的用例是否适用:
解决方案
您可以从使用开始 SOUNDEX()
, ,这可能会满足您的需要(我想象了一个自动建议框,其中包含用户正在输入的内容的现有替代方案)。
的缺点 SOUNDEX()
是:
- 它无法区分较长的字符串。仅考虑前几个字符,末尾分歧的较长字符串会生成相同的 SOUNDEX 值
- 事实上第一个字母必须相同,否则您将无法轻松找到匹配项。SQL Server 有 DIFFERENCE() 函数来告诉你两个 SOUNDEX 值相差多少,但我认为 MySQL 没有内置此类功能。
- 对于 MySQL,至少根据 文档, SOUNDEX 对于 unicode 输入被破坏
例子:
SELECT SOUNDEX('Microsoft')
SELECT SOUNDEX('Microsift')
SELECT SOUNDEX('Microsift Corporation')
SELECT SOUNDEX('Microsift Subsidary')
/* all of these return 'M262' */
对于更高级的需求,我认为你需要看看 编辑距离 (也称为“编辑距离”)两个字符串并使用阈值。这是更复杂(=更慢)的解决方案,但它具有更大的灵活性。
主要缺点是,您需要两个字符串来计算它们之间的距离。使用 SOUNDEX,您可以将预先计算的 SOUNDEX 存储在表中,并对其进行比较/排序/分组/过滤。通过 Levenshtein 距离,您可能会发现“Microsoft”和“Nzcrosoft”之间的差异仅为 2,但需要更多时间才能得出该结果。
无论如何,MySQL 的 Levenshtein 距离函数示例可以在以下位置找到: codejanitor.com:作为 MySQL 存储函数的 Levenshtein Distance(2 月)2007 年 10 日).
其他提示
SOUNDEX是一个不错的算法,这一点,但也出现了关于这一主题的最新进展。另一种算法创建称为音位,它后来被修改为双音位算法。我亲自使用的Java阿帕奇公地执行双音位的并且它是可定制的和准确的。
他们有很多其他语言为它的维基百科页面上的实现了。这个问题已经回答了,但你应该发现任何与SOUNDEX出现在应用程序中发现的问题,它很高兴知道有选项。有时候,它可以产生两种不同的真字相同的代码。双音位是为了帮助需要考虑这个问题的关心。
维基百科被盗: http://en.wikipedia.org/wiki/Soundex
作为在缺陷的响应 Soundex算法,劳伦斯·飞利浦 开发的音位算法 同样的目的。飞利浦以后 开发了一种改进音位, 他称之为双音位。 双音位包括多 更大的编码规则设置为比其 前身处理的一个子集 非拉丁字符,并返回一个 初级和次级编码 考虑到不同的发音 在英语一个字。
在双音位页面的底部,他们有它的实现各种编程语言:的 http://en.wikipedia.org/wiki/Double-Metaphone
的Python和MySQL实现: https://github.com/AtomBoy/double-metaphone
首先,我想补充一点,在使用任何形式的语音/模糊匹配算法时都应该非常小心,因为这种逻辑就是模糊或者更简单地说;可能不准确。当用于匹配公司名称时尤其如此。
一个好的方法是从其他数据中寻求佐证,例如地址信息、邮政编码、电话号码、地理坐标等。这将有助于确认您的数据准确匹配的概率。
与 B2B 数据匹配相关的一系列问题太多,无法在此处解决,我已经写了更多相关内容 公司名称匹配 在我的博客中,但总的来说,关键问题是:
- 作为最重要的部分,查看整个字符串是无济于事的 公司名称不一定在公司的开头 名字。IE。“宝洁公司”或“美国联邦” 保留 '
- 缩写在公司名称中很常见,即惠普、通用、通用、宝洁、 D&B等
- 一些公司故意错误地拼写他们的名字作为 他们的品牌,并将自己与其他公司区分开来。
匹配精确数据很容易,但匹配非精确数据可能会花费更多时间,我建议您应该考虑如何验证非精确匹配,以确保这些数据具有可接受的质量。
在我们建立 Match2Lists.com 之前,我们常常花费大量时间来验证模糊匹配。在 Match2Lists 中,我们采用了强大的可视化工具,使我们能够审查非精确匹配,事实证明,这在匹配验证方面是真正的游戏规则改变者,降低了我们的成本,并使我们能够更快地提供结果。
祝你好运!
这是 soundex 函数的 php 讨论的链接 在 mysql 和 php 中。我将从那里开始,然后扩展到您其他不太明确的需求。
您的参考引用了 Levenshtein 匹配方法。两个问题。1.它更适合测量两个已知单词之间的差异,而不是用于搜索。2.它讨论了一种解决方案,旨在更多地检测校对错误(使用“Levenshtien”表示“Levenshtein”),而不是拼写错误(用户不知道如何拼写,说“Levenshtein”并输入“Levinstein”。我通常将其与在书中查找短语而不是数据库中的键值联系起来。
编辑:回应评论——
- 您至少可以让用户将公司名称输入到多个文本框中吗?2.或使用明确的名称分隔符(例如反斜杠);3.省略冠词(“The”)和通用缩写(或者您可以过滤这些);4.挤压空格并与之匹配(因此 Micro Soft => microsoft,Bare Essentials => bareessentials);5.过滤掉标点符号;6.对单词进行“或”搜索(“裸露”或“必需品”)——有时人们不可避免地会遗漏其中一个。
疯狂地测试并使用用户的反馈循环。
有关模糊匹配的最佳功能的Levenshtein。它是传统上使用的拼写检查程序,所以这可能是要走的路。有它可在这里一个UDF: http://joshdrew.com/
下行使用的Levenshtein是,它不会很好地进行缩放。一个更好的想法可能是放弃整个表中的拼写检查器自定义词典文件,并从应用层,而不是数据库层做的建议。
此答案会导致使用 2 或 3 个或更多字符的输入对几乎所有实体进行索引查找。
基本上,创建一个包含 2 列(单词和键)的新表。对包含要模糊搜索的列的原始表运行一个过程。此过程将从原始列中提取每个单词,并将这些单词与原始键一起写入单词表。在此过程中,应丢弃诸如“the”、“and”等常见单词。
然后我们在单词表上创建几个索引,如下......
- 单词+键上的正常小写索引
- 第 2 个到第 5 个字符的索引 + 键
第 3 到第 6 个字符 + 键的索引
或者,在单词列上创建 SOUNDEX() 索引。
一旦完成,我们将接受任何用户输入并使用普通的 word = input 或 LIKE input% 进行搜索。我们从不执行 LIKE % 输入,因为我们总是在前 3 个字符中寻找匹配项,这些字符都已编入索引。
如果您的原始表很大,您可以按字母表块对单词表进行分区,以确保用户的输入立即缩小到候选行。