Using Postgres SIMILAR TO ...
Don't use SIMILAR TO
. It's utterly pointless. See:
Finding partial matches anywhere in the string is faster with the regular expression match operator ~
(or possibly the case insensitive variant ~*
). To match two strings in arbitrary order, use two expressions to keep it simple. Like:
SELECT * FROM Product p WHERE p.name ~ 'BMW' AND p.name ~ 'i5';
But I suspect you want 'i5' after 'BMW' (with some or no noise in between):
SELECT * FROM Product p WHERE p.name ~ 'BMW.*i5';
Or:
SELECT * FROM Product p WHERE p.name LIKE '%BMW%i5%';
Either can be supported with a trigram index like:
CREATE INDEX ON Product USING gin (name gin_trgm_ops);
Requires the additional module pg_trgm first. See:
Or work with text search. Then you can pass one string with multiple words (lexemes). Your query can look like:
... WHERE to_tsvecor(p.name) @@ plainto_tsquery('simple', 'BMW i5');
Or use phrase search to find 'BMW' followed by 'i5':
... WHERE to_tsvecor(p.name) @@ phraseto_tsquery('simple', 'BMW i5')
See:
Text search is powerful, but you may have to familiarize yourself with it first. The manual provides all you need to know. The index could look like:
CREATE INDEX ON Product USING GIN (to_tsvector('simple', name));
Further reading: