我有以下要求: -
我有很多(比方说100万)值(名字)。 用户将键入搜索字符串。
我不希望用户正确拼写名称。
所以,我想制作一种谷歌“你的意思是”。这将列出我的数据存储区中的所有可能值。有一个类似但不一样的问题here。这没有回答我的问题。
我的问题: - 1)我认为不建议将这些数据存储在RDBMS中。因为那时我不会对SQL查询进行过滤。我必须做全表扫描。那么,在这种情况下应该如何存储数据?
2)第二个问题与this相同。但是,仅仅为了我的问题的完整性:我如何搜索大数据集? 假设,数据集中有一个名称Franky。 如果用户输入Phranky,我该如何匹配Franky?我是否必须遍历所有名称?
我遇到了Levenshtein Distance,这是找到可能的字符串的好方法。但同样,我的问题是我必须对数据存储中的所有100万个值进行操作吗?
3)我知道,Google通过观察用户行为来做到这一点。但我想在不看用户行为的情况下这样做,即通过使用,我还不知道,说距离算法。因为前一种方法需要大量的搜索才能开始!
4)正如答案Kirk Broadhurst中指出的below一样,有两种可能的情况: -
我对这两个都很感兴趣。它们实际上是两个不同的东西;例如Sean和Shawn的声音相同,但编辑距离为3 - 太高而不能被视为拼写错误。
答案 0 :(得分:7)
Soundex算法可以帮助您解决这个问题。
http://en.wikipedia.org/wiki/Soundex
您可以为每个名称预先生成soundex值并将其存储在数据库中,然后对其进行索引以避免必须扫描该表。
答案 1 :(得分:6)
Bitap Algorithm旨在查找文本正文中的近似匹配。也许你可以用它来计算可能的匹配。 (它基于Levenshtein Distance)
(更新:阅读Ben S answer后(使用现有的解决方案,可能aspell
)是可行的方法)
正如其他人所说,谷歌通过观察用户自我纠正来进行自动更正。如果我搜索“someting
”(原文如此),然后立即搜索“something
”,则第一个查询很可能不正确。可能的启发式检测方法是:
然后第二个查询是第一个查询的可能细化,您可以存储并呈现给其他用户。
请注意,您可能需要批次查询来收集足够的数据,以使这些建议有用。
答案 2 :(得分:4)
答案 3 :(得分:3)
这是一个老问题,DWIM(我的意思是什么),由Warren Teitelman在Xerox Alto上实施。如果你的问题是基于发音,这是一份可能有帮助的调查问卷:
学家Zobel和P. Dart,“语音字符串匹配:信息中世纪的教训”, Proc。第19届国际年会。 ACM SIGIR会议信息检索研究与发展(SIGIR'96),1996年8月,第166-172页。
我从事信息检索工作的朋友告诉我,Knuth所描述的Soundex现在被认为已经过时了。
答案 4 :(得分:3)
只需使用Solr或类似的搜索服务器,然后您就不必成为该主题的专家。使用拼写建议列表,对每个建议的结果运行搜索,如果结果多于当前搜索查询,请将其添加为“您是不是的意思”结果。 (这可以防止伪造的拼写建议实际上没有返回更多相关的命中。)这样,你不需要收集大量数据来制作一个初始的“你是说”的产品,尽管Solr有你的机制可以手动调整某些查询的结果。
通常,您不会使用RDBMS进行此类搜索,而是依赖于用于此目的的只读,略微陈旧的数据库。 (Solr为底层的Lucene引擎和数据库添加了友好的编程接口和配置。)在我工作的公司的网站上,每晚服务从RDBMS中选择更改的记录并将它们作为文档推送到Solr中。只需很少的努力,我们就有一个系统,搜索框可以非常有效地搜索产品,客户评论,网站页面和博客条目,并在搜索结果中提供拼写建议,以及您在NewEgg看到的分面浏览, Netflix或Home Depot,在服务器上(特别是RDBMS)几乎没有增加压力。 (我相信Zappo的[新网站]和Netflix都在内部使用Solr,但不要引用我。)
在您的方案中,您将使用名称列表填充Solr索引,并在配置文件中选择适当的匹配算法。
答案 5 :(得分:2)
就像你引用的问题的一个答案一样,Peter Norvig的great solution将为此工作,完成Python代码。谷歌可能会以多种方式查询建议,但他们为他们提供的内容是大量数据。当然,他们可以使用大量查询日志来模拟用户行为,但他们也可以通过查看更常见的更正来使用文本数据来查找单词最可能正确的拼写。单词someting
没有出现在字典中,即使它是常见的拼写错误,正确的拼写也更为常见。当您找到相似的单词时,您希望单词最接近拼写错误,并且在给定的上下文中最可能。
Norvig的解决方案是从古腾堡计划中获取几本书的主语,并计算出现的单词。从这些单词中,他创建了一个字典,您还可以在其中估计单词的概率(COUNT(word) / COUNT(all words)
)。如果将所有内容存储为直接哈希,则访问速度很快,但存储可能会成为问题,因此您还可以使用suffix tries之类的内容。访问时间仍然相同(如果您基于哈希实现它),但存储要求可以少得多。
接下来,他生成拼写错误单词的简单编辑(通过删除,添加或替换字母),然后使用语料库中的字典约束可能性列表。这是基于编辑距离(例如Levenshtein距离)的思想,使用简单的启发式方法,大多数拼写错误发生在2或更小的编辑距离。您可以根据需要和计算能力来扩大这一范围。
一旦他掌握了可能的话,他就会从语料库中找到最可能的单词,这就是你的建议。您可以添加许多内容来改进模型。例如,您还可以通过考虑拼写错误中字母的键盘距离来调整概率。当然,这假设用户正在使用英语的QWERTY键盘。例如,转置e
和q
比转置e
和l
更有可能。
答案 6 :(得分:1)
对于推荐Soundex的人来说,它已经过时了。 Metaphone(更简单)或Double Metaphone(复杂)要好得多。如果它确实是名称数据,它应该工作正常,如果名称是欧洲原产地,或至少是语音。
至于搜索,如果你想自己滚动,而不是使用Aspell或其他一些智能数据结构...预先计算可能的匹配是O(n ^ 2),在幼稚的情况下,但我们知道为了完全匹配,他们必须有“音素”重叠,甚至可能有两个。该预索引步骤(具有低误报率)可以大大降低复杂度(在实际情况下,类似于O(30 ^ 2 * k ^ 2),其中k <&lt;&lt; n) 。
答案 7 :(得分:1)
您有两个可能需要解决的问题(如果您愿意,可以不解决)
您对这两者还是其中一种感兴趣吗?它们实际上是两个不同的东西;例如Sean和Shawn的声音相同,但编辑距离为3 - 太高而不能被视为拼写错误。
您应该对单词的数量进行预先索引,以确保您只是建议相关的答案(类似于ealdent的建议)。例如,如果我输入sith
,我可能会被问到是否表示smith
,但如果我输入smith
则建议使用sith
是没有意义的。确定一种算法,该算法衡量单词的相对可能性,并仅建议更可能的单词。
我在松散匹配方面的经验加强了一个简单但重要的学习 - 根据需要执行尽可能多的索引/筛选层,不要害怕包含超过2或3的内容。剔除任何不正确的内容例如,字母然后剔除没有以正确字母结尾的所有内容,依此类推。您真的只想对最小的数据集执行编辑距离计算,因为它是一个非常密集的操作。
因此,如果你有一个O(n),一个O(nlogn)和一个O(n ^ 2)算法 - 按顺序执行这三个,以确保你只是把你的“好前景”通过你沉重的算法。