我有目录号到产品名的映射:
35 cozy comforter
35 warm blanket
67 pillow
和需要搜索能够找到拼写错误的混合名称,例如“warm cmfrter”。
我们使用edit-distance(difflib)编写代码,但它可能无法扩展到18000个名称。
我实现了与Lucene类似的东西,但是PyLucene只包装了Java,这会使部署复杂化到最终用户。
SQLite通常没有编译的全文或评分。
Xapian bindings就像C ++一样,有一些学习曲线。
Whoosh尚未有详细记录,但包括可滥用的拼写检查程序。
还有什么?
答案 0 :(得分:4)
显然,快速进行模糊比较的唯一方法是减少它们;)
不是编写另一个n-gram搜索或改进Whoosh中的那个,我们现在保留一个单词索引,检索所有与查询共有至少一个(正确拼写)单词的条目,并使用difflib对这些单词进行排名。在这种情况下运作良好。
答案 1 :(得分:2)
Nucular 有全文搜索,但它不支持拼写错误的匹配 盒子外面。您可以尝试为每个条目添加其他字段 哪个索引 SOUNDEX翻译术语,然后使用soundex翻译进行搜索 用户输入。我真的不知道这有多好用......
看一下advas http://advas.sourceforge.net/news.php,它有一个很好的演示,比较各种类似soundex的方法:
advas/examples Aaron$ python phonetic_algorithms.py
soundex metaphone nyiis caverphone
====================================================================================================
schmidt : S253 sxmtt sssnad SKMT111111
schmid : S253 sxmt sssnad SKMT111111
schmitt : S253 sxmt sssnatt SKMT111111
smith : S530 sm0h snatt SMT1111111
smythe : S530 smy0h snatt SMT1111111
schmied : S253 sxmt sssnaad SKMT111111
mayer : M600 myr naaar MA11111111
meier : M600 mr naaar MA11111111
....
我不知道他们中的任何一个是否适合你的未命名语言......
答案 2 :(得分:2)
SOUNDEX实施会产生太多误报。只有26,000(最多)可能的SOUNDEX代码。
虽然Metaphone算法是为英文姓氏设计的,但它对拼写错误非常有效;我在分支定位器中使用过一次它非常成功。
添加带有Metaphone翻译的字段,如果找不到完全匹配,则匹配该字段。你仍会得到误报,但与其他算法相比更少。
答案 3 :(得分:1)
计算两个字符串之间的编辑距离的常用方法是一种相当昂贵的算法(如果我没记错的话,它的时间复杂度是二次的)。也许如果您使用不同的字符串相似性度量标准,那么您的问题就会消失。
我最喜欢的模糊字符串匹配方法之一是trigrams matching。使用此方法比较两个字符串具有线性时间复杂度,这比上述编辑距离要好得多。您可以在Github上找到我的Python实现。完全有一个PostgreSQL contrib module。使它适应SQLite3应该不会太困难。
答案 4 :(得分:1)
Sybase SQL Anywhere有一个免费的网络版/开发人员版,附带全文索引/搜索和FUZZY运算符(以及一些实现约束)。
引用文档:
Specifying 'FUZZY "500 main street"' is equivalent to
'500 OR mai OR ain OR str OR tre OR ree OR eet'.
另一种方法是在全文搜索中使用评分。
答案 5 :(得分:1)
sqlite3支持python回调函数。 Matthew Barnett的正则表达式(http://code.google.com/p/mrab-regex-hg/)现在支持近似匹配。
所以,就像这样:
try:
import regex
except ImportError:
sys.stderr.write("Can't import mrab-regex; see http://pypi.python.org/pypi/regex\n")
sys.exit(1)
def _sqlite3_regex(expr, item):
return (not (not regex.search(expr, item)))
def main():
...
database = sqlite3.connect(dbfile)
database.create_function("regexp", 2, _sqlite3_regex)
pattern = '(?:%s){e<=%d}' % (queriedname, distance)
print [x for x in database.cursor().execute(
"SELECT * FROM products WHERE (productname regexp '%s')" % pattern)]