Как построить эффективную функцию множественных запросов в PostgreSQL? - PullRequest
1 голос
/ 27 марта 2019

Я пытаюсь написать функцию в plpgsql, которая позволила бы мне эффективно запрашивать мою базу данных.Недостаточно стандартных блоков в plpgsql, которые позволили бы мне завершить / отладить мое дело, а именно:

Дело:

Моя база данных содержит более 50 миллионов записей, которые состоят изтекст, темы и метаданные.Это только очень структурированные данные описания, содержащие такие предложения, как
«большой коричневый ствол в локации» или «невероятно разный подход». Tsvector обеспечит запись с наивысшим соответствием, если каждое слово написано правильно независимо от того, в каком порядке или в каком порядке.терпит неудачу, если пользователь пропускает заклинания.Я использовал pg_tgrm как запасной вариант для него, который соответствовал бы с помощью Similarity () или word_sdentifity (). Если я упорядочил результат соответственно

, я проиндексировал два столбца, используя pg_tgrm и tsvector.Я хочу иметь возможность поиска функции (user_text, user_theme), которая возвращает записи путем сопоставления пользовательской темы и ввода в методы индексации текста pg_tgrm или tsvector.

В псевдокоде:

func lookup(user_input text, user_theme text) -> [score, record]:
var user_input_tsquery <- replace_char(user_input, ' ', ' & ')

if user_theme in database:
    subdatabase <- A set of entries where database.theme = user_theme

    var record <- subdatabase.tsvector = user_input_tsquery
    var result_rank <- rank(subdatabase.tsvector = user_input_tsquery)

    if record is not empty:
        return [result_rank, record]

    else
        var record <- subdatabase.pg_tgrm = user_input
        var simil <- similarity(subdatabase.pg_tgrm = user_input)
        return [simil, record]
else
    var record <- database.tsvector = user_input_tsquery
    var result_rank <- rank(database.tsvector = user_input_tsquery)

    if record is not empty:
        return [result_rank, record]

    else
        var record <- database.pg_tgrm = user_input
        var simil <- similarity(database.pg_tgrm = user_input)
    return [simil, record]

С plpgsql действительно сложно справиться.Я пытался написать функцию небольшими частями моей функции запроса, но просто пытался отладить, как составить возвращаемое значение или мне нужен TABLE или SETOF, поскольку вывод составной записи разочаровывает.

CREATE OR REPLACE FUNCTION lookup_test(user_input text, user_theme text) RETURNS TABLE AS $$
DECLARE user_input_ts text;
DECLARE ress TABLE;
DECLARE result TABLE(score double, summary text);
BEGIN
SELECT REPLACE(LOWER(user_input), ' ', ' & ') INTO user_input_ts;

CASE WHEN EXIST(SELECT * from database WHERE theme = user_theme)
    THEN
        CASE
            SELECT * from database WHERE theme = user_theme INTO ress;
            WHEN EXIST(SELECT least(ts_rank(ts_summary, user_input_ts, 32), 1.0) AS score, id_source
                       FROM ress
                       WHERE ts_sumnmary @@ to_tsquery('english', user_input_ts))
            THEN RETURN ress;

           SELECT tgrm_summary <-> user_input as score, *
           FROM ress WHERE tgrm_summary % user_input
        END CASE;
        END;
END;
$$ LANGUAGE plpgsql;

Iне имею опыта работы с plpgsql.Я использую pg_tgrm и tsvector, потому что первый нечетко совместим, но медленен, а второй действительно быстр, но требует точной типизации, поэтому я хотел узнать, смогу ли я получить умный результат, который будет использовать индексацию tsvector, и в случае неудачи попытаться с индексированием pg_tgrmБолее того, если пользователь предоставляет тему, используйте ее как способ уменьшить количество записей, которые нужно искать.

...