7

我正在使用pg_search gem. 但是,其中一个表有一个Text数据类型字段,它的内容恰好比平时大一点。

现在,当我需要tsvector columntext列设置 a 时,由于文本字段大小与 tsvector 大小的关系,我面临一些限制。

ERROR: string is too long for tsvector (5068741 bytes, max 1048575 bytes)

在触发器中Text创建 tsvector 列以执行以下操作时,有什么方法可以确定跳过更大字段的条件:SQL

伪代码:

execute(<<-TRIGGERSQL)
CREATE OR REPLACE FUNCTION public.essays_before_insert_update_row_tr()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
BEGIN
    If (SELECT LEN(body_text) FROM essays) <= 1048575
      new.tsv_body_text := to_tsvector('pg_catalog.english', coalesce(new.body_text,''));
      RETURN NEW;
    End
END;
$function$
  TRIGGERSQL

  # no candidate create_trigger statement could be found, creating an adapter-specific one
  execute("CREATE TRIGGER essays_before_insert_update_row_tr BEFORE INSERT OR UPDATE ON \"essays\" FOR EACH ROW EXECUTE PROCEDURE essays_before_insert_update_row_tr()")

我发现没有答案的相关问题:

Postgresql - 将文本转换为 ts_vector

4

1 回答 1

5

一个简单的解决方法是只to_tsvector()使用截断的文本值进行调用。例如,使用 Postgres 手册中的触发器示例作为起点,此方法如下所示:

CREATE FUNCTION essays_tsv_trigger_fn() RETURNS trigger AS $$
begin
    new.tsv_body_text := to_tsvector('english', left(new.body_text, 4*1024*1024));
    return new;
end
$$ LANGUAGE plpgsql;

CREATE TRIGGER essays_tsv_trigger BEFORE INSERT OR UPDATE
    ON essays FOR EACH ROW EXECUTE FUNCTION essays_tsv_trigger_fn();

这会将文档的内容截断为 4 MiB,这对于许多文档集合应该足够有用。而不是仅仅忽略“过长”的文档,您至少包括其中的一部分。根据我的经验,4 MiB 非常适合技术英语文档。根据实际使用的词汇量的大小,您甚至可以在截断更大的值(如 10 MiB)时成功。

如果你真的想忽略太长的文档,你可以to_tsvector()使用这样的 if 语句来保护赋值:

CREATE FUNCTION essays_tsv_trigger_fn() RETURNS trigger AS $$
begin
    if length(new.body_text) <= 4*1024*1024 then
        new.tsv_body_text := to_tsvector('english', new.body_text);
    end if;
  return new;
end
$$ LANGUAGE plpgsql;
于 2019-08-10T15:35:59.380 回答