Let's imagine this is your table and some data:
CREATE TABLE t
(
country text,
city text,
street text,
house_number text,
post_code text
) ;
INSERT INTO t
VALUES
('Österreich', 'Vienna', 'HauptStrasse', '123', '12345'),
('France', 'Paris', 'Rue du Midi', '12A', '01234'),
('España', 'Barcelona', 'Passeig de Gràcia', '32', '08001'),
('United Kingdom', 'London', 'Oxford Street', '20', 'W1D 1AS'),
('Nederland', 'Amsterdam', 'Leidsekruisstraat', '6-8', '1017 RH') ;
[NOTE: check it at http://rextester.com/DOJN8533]
The way to perform a full text search to several columns using PostgreSQL (assuming 'english' is the name of your FTS configuration), is by using a query like:
SELECT
*
FROM
t
WHERE
(
to_tsvector('english', coalesce(country, '')) ||
to_tsvector('english', coalesce(city, '')) ||
to_tsvector('english', coalesce(street, '')) ||
to_tsvector('english', coalesce(house_number, '')) ||
to_tsvector('english', coalesce(post_code, ''))
) @@ plainto_tsquery('english', 'Amsterdam') ;
The where clasuse means:
(this tsvector = document) @@ /* matches */ (this tsquery = query)
A tsvector is a special data type used by PostgreSQL to store transformed data (for instance, all lowercased; with commas taken out, with words identified and listed, etc.) about a text. A tsquery is a way to ask for characteristics of a document (for instance containing this _and_ that).
The || operator combines tsvectors (let's say it "adds them together").
If you want to speed up things, you should have one functional index, defined like:
CREATE INDEX ts_idx
ON t USING gist (
(
to_tsvector('english', coalesce(country, '')) ||
to_tsvector('english', coalesce(city, '')) ||
to_tsvector('english', coalesce(street, '')) ||
to_tsvector('english', coalesce(house_number, '')) ||
to_tsvector('english', coalesce(post_code, ''))
)
) ;
You need to carefully check the documentation about Full Text Search. It is a bit intimidating, because there are lots of possibilities, but it's worth spending the time.
To sort out results when there are many, you should use he ts_rank function to ORDER BY and then limit.
concat_ws()is notIMMUTABLE. I added a solution and explanation above. – Erwin Brandstetter Feb 12 '17 at 19:41unaccent: You could integrate the functionunaccent()(the 2-parameter form like instructed here!) inf_concat_ws()and call itf_unaccent_concat_ws()or something. But you should always unaccent search arguments likewise to make it work! (And be aware of possible false matches due to the simplification.) The advanced solution would be to create a new text search configuration that uses the unaccent dictionary automatically. But that may be too advanced for you right now. – Erwin Brandstetter Feb 12 '17 at 19:57GENERATEDcolumn). It makes index and bitmap index plan nodes a bit faster (but not index-only), because Postgres does not have repeat the concatenation to recheck an index condition in the heap tuple. But it adds overhead, write cost, and the table is bloated by the redundant column (long strings amplify the downside), which adds cost to everything else. It all depends ... – Erwin Brandstetter Oct 01 '23 at 19:09