如何在PostgreSQL中构建高效的多查询函数?

如何在PostgreSQL中构建高效的多查询函数?,postgresql,plpgsql,Postgresql,Plpgsql,我正在尝试用plpgsql编写一个函数,使我能够高效地查询数据库。plpgsql的构建块不足,无法完成/调试我的案例,具体如下: 案例: 我的数据库包含5000多万条记录,其中包括文本、主题和元数据。 它只是非常结构化的描述数据,包含以下语句 如果每个单词拼写正确,不管顺序如何,一个大的棕色主干或一个令人难以置信的不同方法tsvector将提供最高的匹配条目,如果用户拼写错误,它将失败。我使用pg_tgrm作为它的回退,如果我对结果进行相应排序,它将使用相似性或单词相似性进行匹配 我使用pg_t

我正在尝试用plpgsql编写一个函数,使我能够高效地查询数据库。plpgsql的构建块不足,无法完成/调试我的案例,具体如下:

案例:

我的数据库包含5000多万条记录,其中包括文本、主题和元数据。
它只是非常结构化的描述数据,包含以下语句 如果每个单词拼写正确,不管顺序如何,一个大的棕色主干或一个令人难以置信的不同方法tsvector将提供最高的匹配条目,如果用户拼写错误,它将失败。我使用pg_tgrm作为它的回退,如果我对结果进行相应排序,它将使用相似性或单词相似性进行匹配

我使用pg_tgrm和tsvector为两列建立了索引。 我希望能够有一个函数lookupuser_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;

我没有使用plpgsql的经验。我使用pg_tgrm和tsvector,因为前者是模糊兼容的,但速度很慢,而后者非常快,但需要精确的键入,所以我想处理我是否可以得到一个使用tsvector索引的智能结果,如果失败,则尝试使用pg_tgrm索引,此外,如果用户提供主题,然后用它来减少要查找的条目数量。

您应该从定义确切的需求开始。全文搜索和相似性匹配是完全不同的。成功匹配的条件是什么?它只是非常结构化的描述数据。数据库中包含一些句子,例如某个位置的一个大棕色主干,或者一种难以置信的不同方法。如果每个单词拼写正确,无论顺序如何,tsvector都将提供最高匹配条目,如果用户拼写错误,它将失败。我使用pg_tgrm作为它的后备方法,如果我按照顺序排列结果,它将使用相似性或单词相似性进行匹配。您不需要使用EXISTSELECT*from database WHERE theme=user_theme然后->>尝试选择不存在的记录是犯罪的。这看起来不像是有效的PL/pgSQL。声明ress表;是一个语法错误。您不是在使用常规的PostgreSQL吗?您应该从定义确切的需求开始。全文搜索和相似性匹配是完全不同的。成功匹配的条件是什么?它只是非常结构化的描述数据。数据库中包含一些句子,例如某个位置的一个大棕色主干,或者一种难以置信的不同方法。如果每个单词拼写正确,无论顺序如何,tsvector都将提供最高匹配条目,如果用户拼写错误,它将失败。我使用pg_tgrm作为它的后备方法,如果我按照顺序排列结果,它将使用相似性或单词相似性进行匹配。您不需要使用EXISTSELECT*from database WHERE theme=user_theme然后->>尝试选择不存在的记录是犯罪的。这看起来不像是有效的PL/pgSQL。声明ress表;是一个语法错误。你没有使用常规的PostgreSQL吗?