使用 Postgres SIMILAR TO 和 Spring Data 匹配列中的子字符串

问题描述

我在一个列中有一个值为“非常好的 BMW 4 轮驱动 i5”的记录。

如果我提供此值的子字符串,如何进行查询以找到此值?假设我想通过提供这个“BMW i5”来找到它?

如果我使用 LIKE 方法,那么它期望单词按顺序排列。

@Query("SELECT p FROM Product p WHERE p.name LIKE CONCAT('%',:name,'%')")

我正在使用带有 Spring DATA 的 Spring Boot。数据库是 postgres。

如果我用这个查询在 Postgres 上搜索字符串,我可以找到它,所以问题是如何用 Spring DATA 来做:

select name from product WHERE name similar TO '%((BMW) | (i5))%'

解决方法

使用 Postgres 类似于 ...

不要。切勿使用 SIMILAR TO。这完全没有意义。见:

使用正则表达式匹配运算符 ~(或可能不区分大小写的变体 ~*)可以更快地在字符串中的任何位置查找部分匹配。要以任意顺序匹配 两个 字符串,请使用 two 表达式以保持简单。喜欢:

SELECT * FROM Product p WHERE p.name ~ 'BMW' AND p.name ~ 'i5';

但我怀疑你想要“i5”“BMW”(中间有噪音或没有噪音):

SELECT * FROM Product p WHERE p.name ~ 'BMW.*i5';

或者:

SELECT * FROM Product p WHERE p.name LIKE '%BMW%i5%';

可以使用三元组索引来支持,例如:

CREATE INDEX ON Product USING gin (name gin_trgm_ops);

首先需要附加模块 pg_trgm。见:

text search一起工作。然后你可以传递一个包含多个单词(词素)的字符串。您的查询可能如下所示:

... WHERE to_tsvecor(p.name) @@ plainto_tsquery('simple','BMW i5');

或者使用短语搜索来查找'BMW'后跟'i5'

... WHERE to_tsvecor(p.name) @@ phraseto_tsquery('simple','BMW i5')

见:

文本搜索功能强大,但您可能必须先熟悉它。该手册提供了您需要了解的所有信息。索引可能如下所示:

CREATE INDEX ON Product USING GIN (to_tsvector('simple',name));

进一步阅读: