Нормализация БД или удобство запросов?

Подскажите пожалуйста, например у нас есть сайт с описанием автомобилей. Возьмём один из них: описание Porsche 911 GT2 992. У нас будут повторяться и марка и модель и номер кузова, поэтому их мы выведем в отдельные таблицы, как рекомендовано это делать, и в конце концов из БД мы сможем получить, что-то такое:

Porsche | 911 | GT2 | 992 |описание

А теперь представим, что пользователь ищет описание для этого автомобиля через наш поиск.

И отправляет через поиск “Porsche 911”

У нас нет ни в одной ячейки БД «porsche 911» нам нужно вначале обьединить 4 колонки и уже потом делать поиск. Но это как-то не изящно для 2021 года. Если запихать марку, модель, номер кузова в одну ячейку - то это как-то не правильно с точки зрения нормализации, да и фильтровать например по марке или кузову станет сложнее. Как быть? Есть 3-й сценарий? Полнотекстовый поиск? Или это дорого для такого случая?


Ответы (1 шт):

Автор решения: Roman Konoval

Объединять все в одну ячейку не стоит, т.к. это не будет работать, если пользователь скажем введет не "Porsche 911", а "911 Porsche". Наверняка, вы захотите, чтоб в этом случае тоже находился результат.

И тут без полнотекстового поиска не обойтись. Можно использовать встроенный или внешний (типа solr или elasticsearch).

Для встроенного это может выглядеть так:

create table auto (manufacturer text, model text, body text);
insert into auto values ('Porsche', '911 GT', '992');

=> SELECT * from auto where to_tsvector('english', manufacturer || ' ' ||  model || ' ' ||  body) @@ to_tsquery(E'\'Porsche 992\'');
 manufacturer | model  | body
--------------+--------+------
 Porsche      | 911 GT | 992
(1 row)

можно создать индекс, для того чтобы данные парсились один раз при вставке

create index auto_full_text on auto
  using gin(to_tsvector('english', manufacturer || ' ' ||  model || ' ' ||  body));
→ Ссылка