Can the pg_search full-text-search (tsearch) do both prefix and dictionary searching at the same time?

39 Views Asked by At

I've been fiddling with pg_search. Using tsearch, I have managed to set up a dictionary search and a prefix search. However, if I search by a dictionary term, it won't also yield the results for the prefix search. I was wondering if there is a way to have them both work simultaneously.

For example, a line in my dictionary looks something like this:

wheat grain food bread

If I search for "bread" everything titled "wheat" "grain" "food" or "bread" will appear.

But if I had an item titled "breadman" it should appear when "bread" is searched, because prefix search is true. But it doesn't unless I remove the dictionary or type a partial word like "brea" or "breadma".

Code for referenece:

  pg_search_scope :search_title, lambda { |query, params| 
    {
      query: query,
      against: :title,
      using: {
        tsearch: {
            dictionary: 'english', prefix: true
        }
      }
    }

As mentioned above, I have tried having both dictionary and prefix working at the same time. However it does not appear that prefix works if a dictionary item is searched for.

1

There are 1 best solutions below

5
Laurenz Albe On

I don't know what pg_search is doing, but you can use a synonym dictionary.

  • create a file mysyn.syn in the tsearch_data subdirectory of the PostgreSQL "share" directory containing

    wheat bread
    grain bread
    food bread
    
  • create a synonym dictionary:

    CREATE TEXT SEARCH DICTIONARY mysyn (
       TEMPLATE = synonym,
       SYNONYMS = mysyn
    );
    
  • create a text search configuration:

    CREATE TEXT SEARCH CONFIGURATION mycf (COPY = english);
    ALTER TEXT SEARCH CONFIGURATION mycf
       ALTER MAPPING FOR asciiword WITH mysyn, english_stem;
    

That should work as desired for prefix search:

SELECT to_tsvector('mycf', 'food') @@ to_tsquery('mycf', 'bread:*');

 ?column? 
══════════
 t
(1 row)

SELECT to_tsvector('mycf', 'breadbox') @@ to_tsquery('mycf', 'bread:*');

 ?column? 
══════════
 t
(1 row)