Alv*_*lve 36 sql postgresql fuzzy-search ruby-on-rails
我的基于RoR的网站上的搜索功能有点问题.我有很多产品和一些CODE.此代码可以是任何字符串,如"AB-123-lHdfj".现在我使用ILIKE运算符来查找产品:
Product.where("code ILIKE ?", "%" + params[:search] + "%")
Run Code Online (Sandbox Code Playgroud)
它工作正常,但找不到像"AB123-lHdfj"或"AB123lHdfj"这样的代码的产品.
我该怎么办?可能是postgresql有一些字符串规范化功能,还是其他一些方法来帮助我?:)
Pau*_*sik 52
Postgres提供了一个带有多个字符串比较函数的模块,例如soundex和metaphone.但是你会想要使用levenshtein编辑距离函数.
Example:
test=# SELECT levenshtein('GUMBO', 'GAMBOL');
levenshtein
-------------
2
(1 row)
Run Code Online (Sandbox Code Playgroud)
这2是两个单词之间的编辑距离.当您对多个单词应用此单词并按编辑距离结果排序时,您将获得您正在寻找的模糊匹配类型.
试试这个查询示例:(当然有你自己的对象名和数据)
SELECT *
FROM some_table
WHERE levenshtein(code, 'AB123-lHdfj') <= 3
ORDER BY levenshtein(code, 'AB123-lHdfj')
LIMIT 10
Run Code Online (Sandbox Code Playgroud)
这个查询说:
给我来自some_table的所有数据的前10个结果,其中代码值和输入'AB123-lHdfj'之间的编辑距离小于3.您将获得代码值在3个字符之内的所有行的差异' AB123-lHdfj" ...
注意:如果您收到如下错误:
function levenshtein(character varying, unknown) does not exist
Run Code Online (Sandbox Code Playgroud)
fuzzystrmatch使用以下命令安装扩展
test=# CREATE EXTENSION fuzzystrmatch;
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 41
保罗告诉过你levenshtein().这是一个非常有用的工具,但是对于大表来说它也很慢.它必须计算每一行搜索项的levenshtein距离,这是昂贵的.
首先,如果您的要求与示例所示一样简单,您仍然可以使用LIKE.只需将-搜索词中的any替换%为创建WHERE子句即可
WHERE code LIKE "%AB%123%lHdfj%"
Run Code Online (Sandbox Code Playgroud)
代替
WHERE code LIKE "%AB-123-lHdfj%"
Run Code Online (Sandbox Code Playgroud)
如果你真正的问题更复杂,你需要更快的东西 - 根据你的要求 - 有几种选择.
当然还有全文搜索.但在你的情况下,这可能是一种矫枉过正.
更可能的候选人是pg_trgm.请注意,您可以将它与LIKEPostgreSQL 9.1 结合使用.请参阅Depesz的这篇博客文章.
在这种情况下也非常有趣:该模块的similarity()功能或%操作员.更多:
最后但并非最不重要的是,您可以实现一个手工编织的解决方案,其中包含一个函数来规范化要搜索的字符串.例如,您可以转换AB1-23-lHdfj- > ab123lhdfj,将其保存在附加列中,并使用以相同方式转换的搜索项进行搜索.
或者在表达式上使用索引而不是冗余列.(涉及的功能必须是IMMUTABLE.)并且可能将其与pg_tgrm上面的结合起来.
模式匹配技术概述:
| 归档时间: |
|
| 查看次数: |
32520 次 |
| 最近记录: |