Search code examples
sqlpostgresqlfull-text-searchtsvector

Postgres tsvector with relational tables


I have two simple tables. First is brands and each brand may have a top brand. For example Elseve has a top brand which is Loreal Paris. But Avon has no top brand. And I have a simple products table.

Here is sqlfiddle

Here is brands table.

 id |     name     | parent_id | depth
----+--------------+-----------+-------
  3 | Loreal Paris |     null  |     0
  1 | Avon         |     null  |     1
  2 | Elseve       |      3    |     1
(3 rows)

And here is products table

 id | brand_id |   name
----+----------+-----------
  1 |        1 | Product 1
  2 |        2 | Product 2
(2 rows)

When I try to get tsvectors, Product 1 document returns null result. But I need to get at least Avon in the document.

 product_id | product_name |                     document
------------+--------------+--------------------------------------------------
          1 | Product 1    |
          2 | Product 2    | '2':2 'elsev':3 'loreal':4 'paris':5 'product':1
(2 rows)

How to solve this problem ?

Thanks to Voa Tsun. I updated query a little bit. I don't need grouping anymore.

select
  products.id as product_id,
  products.name as product_name,
  to_tsvector(products.name) ||
  to_tsvector(brands.name) ||
  to_tsvector(top_brands.name)
    as document
from products
  JOIN brands on brands.id = products.brand_id
  LEFT JOIN brands as top_brands on coalesce(brands.parent_id,brands.id) = top_brands.id;

Solution

  • The basic idea is to join id not against null in "parent_id", but "at least against id", as I got from your post. like here:

       select
          products.id as product_id,
          products.name as product_name,
          to_tsvector(coalesce(products.name,brands.name)) ||
          to_tsvector(brands.name) ||
          to_tsvector(coalesce(string_agg(top_brands.name, ' ')))
            as document
        from products
          JOIN brands on brands.id = products.brand_id
          LEFT JOIN brands as top_brands on coalesce(brands.parent_id,brands.id) = 
         top_brands.id
        GROUP BY products.id,brands.id;
    
        product_id  product_name    document
    1   1   Product 1   '1':2'avon':3,4'product':1
    2   2   Product 2   '2':2'elsev':3'loreal':4'pari':5'product':1