如何仅用PostgreSQL创建简单的模糊搜索?

roqulrg3  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(130)

我有一个小问题,搜索功能对我的RoR为基础的网站。我有许多产品与一些代码。此代码可以是任何字符串,如“AB-123-lHdfj”。现在我使用ILIKE操作符来查找产品:

Product.where("code ILIKE ?", "%" + params[:search] + "%")

字符串
它工作正常,但它找不到代码为“AB 123-lHdfj”或“AB 123 lHdfj”的产品。
我该怎么办?可能是Postgres有一些字符串规范化函数,或者其他一些方法可以帮助我?

tjjdgumg

tjjdgumg1#

Postgres提供了一个模块,其中包含几个字符串比较函数,例如soundex和metaphone。但是你需要使用levenshtein编辑距离功能。

Example:

test=# SELECT levenshtein('GUMBO', 'GAMBOL');
 levenshtein
-------------
           2
(1 row)

字符串
2是两个单词之间的编辑距离。当您对许多单词应用此方法并按编辑距离结果进行排序时,您将获得要查找的模糊匹配类型。
试试这个查询示例:(当然,使用您自己的对象名称和数据)

SELECT * 
FROM some_table
WHERE levenshtein(code, 'AB123-lHdfj') <= 3
ORDER BY levenshtein(code, 'AB123-lHdfj')
LIMIT 10


这个查询说:
给予我some_table中所有数据的前10个结果,其中代码值和输入'AB 123-lHdfj'之间的编辑距离小于3。您将返回代码值与'AB 123-lHdfj'相差3个字符以内的所有行。
注意:如果你得到一个错误,比如:

function levenshtein(character varying, unknown) does not exist


使用以下命令安装fuzzystrmatch扩展:

test=# CREATE EXTENSION fuzzystrmatch;

qcbq4gxm

qcbq4gxm2#

保罗告诉你levenshtein()的事了。这是一个非常有用的工具,但它在大表上也非常慢。它必须从每一行的搜索项中计算Levenshtein distance。这是昂贵的,不能使用索引。“加速”变体levenshtein_less_equal()对于长字符串更快,但在没有索引支持的情况下仍然很慢。
如果您的需求像示例所示的那样简单,您仍然可以使用LIKE。只需将搜索词中的任何-替换为WHERE子句中的%。因此,而不是:

WHERE code ILIKE '%AB-123-lHdfj%'

字符串
用途:

WHERE code ILIKE '%AB%123%lHdfj%'


或者,动态地:

WHERE code ILIKE '%' || replace('AB-123-lHdfj', '-', '%') || '%'


LIKE模式中的%代表0-n个字符。或者只对一个字符使用_。或者使用正则表达式进行更智能的匹配:

WHERE code ~* 'AB.?123.?lHdfj'


.? ... 0或1个字符
或者:

WHERE code ~* 'AB\-?123\-?lHdfj'


\-? ... 0或1个破折号
您可能希望转义LIKE或regexp模式中的特殊字符。请参阅:

  • 正则表达式或LIKE模式的转义函数

如果您的实际问题更复杂,并且您需要更快的解决方案,那么根据您的要求,有各种选择:

  • 当然还有full text search。但这对你来说可能有点过了。
  • 更可能的候选是与附加模块pg_trgm的三元组匹配。请参阅:
  • 对tsvector中的每个元素使用Levenshtein函数?
  • PostgreSQL LIKE查询性能变化
  • Related blog post by Depesz

可以与LIKEILIKE~~*组合使用,自PostgreSQL 9.1起。
在这方面也很有趣:该模块的similarity()函数或%运算符。

  • 最后但并非最不重要的一点是,你可以用一个函数来实现一个手工编织的解决方案,以规范化要搜索的字符串。例如,您可以转换AB1-23-lHdfj--> ab123lhdfj,将其保存在一个附加列中,并使用以相同方式转换的术语进行搜索。

或者使用index on the expression代替冗余列。(涉及的函数必须是IMMUTABLE。)可以将其与上面的pg_tgrm组合。
模式匹配技术概述:

相关问题