результаты поиска синонима и префикса postgres вместе

#postgresql #full-text-search

#postgresql #полнотекстовый поиск

Вопрос:

У меня есть синонимы: озеро лак лох Когда я делаю fts в postgres для «озера», я хочу получить все слова, содержащие «озеро», «лак» и «озеро» (которые я использую синонимами либо в виде файла .syn, либо в виде файла .rules). Тем не менее, я также хочу получить слова, начинающиеся с «lake», например «lakefield». Если я использую синонимы, я не получаю совпадений с префиксами, когда я не использую синонимы, я получаю совпадения с префиксами… Как я могу получить и то, и другое? Есть ли способ отключить синонимы, чтобы я задал один вопрос, чтобы получить синонимы, а другой игнорировал их? Я пробовал использовать «нравится» и «позиция», но это слишком медленно.

.правила имеют: озеро лак лох лох озеро лак лак озеро лох

.синоним: озеро гггг лак гггг озеро гггг

Я попробовал и то, и другое, но та же проблема. Если я сопоставлю все синонимы с одним из них в файле .syn: lake озеро лак озеро лох озеро

… Я получу ‘lakefield’, но не ‘lacombe’ (и мне нужно, чтобы они все работали с префиксом).

Я использую PostgreSQL 9.3.

Запрос заключается в следующем:

 select 
    *, 
    ts_rank_cd(to_tsvector('location', name), to_tsquery('location', 'lac:*'),16) as ftsrank
from profile_name 
where iso_code='en-CA' 
  AND to_tsvector('location', name) @@ to_tsquery('location', 'lac:*') 
  AND ts_rank_cd(to_tsvector('location', name), to_tsquery('location', 'lac:*'),16) >= 0
order by ftsrank desc 
 

В profile таблице есть name поле, по которому я хочу выполнить поиск.

Спасибо, Зорица

Комментарии:

1. Вы должны опубликовать инструкцию SQL, которую вы используете, чтобы мы могли помочь вам в этом

2. Спасибо, Сорен, справедливое замечание. Вот так: select *, ts_rank_cd(to_tsvector('location', name), to_tsquery('location', 'lac:*'),16) as ftsrank from profile_name where iso_code='en-CA' AND to_tsvector('location', name) @@ to_tsquery('location', 'lac:*') AND ts_rank_cd(to_tsvector('location', name), to_tsquery('location', 'lac:*'),16) >= 0 order by ftsrank desc в таблице «профиль» есть поле «имя», по которому мне нравится искать.

3. Это очень интересная проблема. Я не знаю ответа на этот вопрос с самого начала. Если вы не получили ответа здесь, пожалуйста, отправьте подробный вопрос в список рассылки pgsql-general с темой типа «Объединение сопоставления префиксов и синонимов в tsearch?» . Включите ссылку на этот вопрос внизу, и если вы опубликуете сообщение на -general, пожалуйста, прокомментируйте это здесь, чтобы другие могли найти его позже.

Ответ №1:

Вот как я решил проблему: я добавил новую конфигурацию fts (полнотекстовый поиск), которая не использует синонимы, и сослался на нее в to_tsquery по ключевому слову, введенному пользователем для поиска. Для моего примера выше это выглядит так:

 select 
    *, 
    ts_rank_cd(to_tsvector('location', name), to_tsquery('location_nosyn', 'lac:*'),16) as ftsrank
from profile_name 
where iso_code='en-CA' 
  AND to_tsvector('location', name) @@ to_tsquery('location_nosyn', 'lac:*') 
  AND ts_rank_cd(to_tsvector('location', name), to_tsquery('location_nosyn', 'lac:*'),16) >= 0
order by ftsrank desc 
 

… где ‘location_nosyn’ упоминается конфигурация fts, которая не распознает синонимы. Обратите внимание, что я по-прежнему использую синонимы для поля базы данных ‘name’, поэтому оно будет извлекать все синонимы из базы данных. Однако отсутствие синонимов для ключевого слова сохраняет частичные совпадения (если пользователь ввел «lac», он получит синонимичные слова, такие как «Lake», но они также получат «Lacey», но НЕ «Lakewood» … это именно то, что мне нужно).

Надеюсь, это поможет кому-то еще справиться с подобной проблемой. Спасибо всем, кто ответил!

Ответ №2:

Не могли бы вы использовать функцию перезаписи запроса?

 select
ts_rewrite('lake'::tsquery, 'lake'::tsquery, 'lake:* | lac | loch'::tsquery) @@ 'lake'::tsvector, --true
ts_rewrite('lake'::tsquery, 'lake'::tsquery, 'lake:* | lac | loch'::tsquery) @@ 'loch'::tsvector, --true
ts_rewrite('lake'::tsquery, 'lake'::tsquery, 'lake:* | lac | loch'::tsquery) @@ 'lakefield'::tsvector --true
 

Вы также можете сохранить повторную запись вашего запроса в таблицах базы данных.

Комментарии:

1. Спасибо, Нил. Это выглядит как альтернатива использованию расширений синонимов. Поскольку я уже нашел решение, я публикую его в качестве ответа, не говоря уже о том, что ваш нет… Я просто не пробовал … 🙂 Спасибо!