Postgres websearch_to_tsquery проблема с запросом в котором слова на разных языках

У меня есть задача полнотекстового поиска в полях, которые могут содержать русские, английские и смешанные слова. Пользовательский ввод предполагает, что запрос содержит слова на обоих языках. При этом я хотел бы, чтобы слова из запроса искались по ИЛИ.

Для решения этой задачи я построил следующий индекс

CREATE OR REPLACE FUNCTION make_tsvector (name text)
    RETURNS tsvector AS $$
BEGIN
    RETURN (setweight(to_tsvector('russian', name), 'A') || setweight(to_tsvector('english', name), 'B'));
END
$$ LANGUAGE 'plpgsql' IMMUTABLE;

CREATE INDEX projects_fts_name_idx ON projects USING gin (make_tsvector(name)); 

и использую следующий запрос к базе:

find = find.replace(' ', ' OR ');
result = await pool.query(`
                SELECT *,
                    ts_rank(make_tsvector(name), q_ru) AS r_ru,
                    ts_rank(make_tsvector(name), q_en) AS r_en
                FROM projects_v,
                    websearch_to_tsquery('russian', $1) AS q_ru,
                    websearch_to_tsquery('english', $1) AS q_en
                WHERE make_tsvector(name) @@ q_ru AND make_tsvector(name) @@ q_en
                ORDER BY r_ru DESC, r_en DESC
                LIMIT $2 OFFSET $3`,
                [ find, limit, offset ]);

При этом возникает следующая проблема:

Пусть есть поисковый запрос "good day день который"

websearch_to_tsquery('russian', $1) converts to "'good' | 'day' & 'ден' & 'котор'"
websearch_to_tsquery('english', $1) converts to "'good' | 'day' & 'день' & 'который'"

т.е. по какой-то причине, если слова есть на обоих языках, то русские "слова" при конвертации перечисляются через &

Теперь оставим только русские слова "день который" и получим:

websearch_to_tsquery('russian', $1) converts to "'ден' | 'котор'"
websearch_to_tsquery('english', $1) converts to "'день' | 'который'"

т. е. если слова только русские, то они разделяются знаком | (как я и хотел).

Как сделать так, чтобы слова всегда разделялись знаком | ? Или, может быть, есть какой-то другой способ решить мою проблему?


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

Автор решения: Alexander Fedorov

У меня вылетело из головы, что replace() при таком вызове сделает только одну первую замену!

→ Ссылка