0

我想在我的 tsvector 列中使用 postgresql 的 unaccent contrib 包。我已经使用 create extension unaccent 成功安装了该软件包,并检查了它是否有效。我设置了一个触发器来自动更新 tsvector 列,

CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
ON artists FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(tsv_name, 'pg_catalog.simple', name);

然后使用以下命令在所有现有行上设置 tsv_name 列

UPDATE artists SET tsv_name = (to_tsvector('simple', coalesce(name, '')));

我认为我可以通过在上面的代码中简单地将 name 替换为 unaccent(name) 来合并 unaccent 包,但这会在创建触发器代码中引发语法错误。如何解决此问题以确保 tsvector 列使用非重音字符?

4

1 回答 1

2

我知道这是一张非常旧的票,但伴随着@ErwinBrandstetter 令人难以置信的答案(https://stackoverflow.com/a/11007216/5261969)和一些 PostgreSQL 文档阅读(https://www.postgresql.org/docs /9.3/functions-textsearch.html),我终于想通了。

这是我的迁移的样子(使用 Rails 5.2):


    # Erwin's wrapper code
    connection.execute(<<-EOSQL)
      CREATE OR REPLACE FUNCTION public.immutable_unaccent(regdictionary, text)
        RETURNS text LANGUAGE c IMMUTABLE STRICT AS
        '$libdir/unaccent', 'unaccent_dict';
    EOSQL

    connection.execute(<<-EOSQL)
      CREATE OR REPLACE FUNCTION public.f_unaccent(text)
        RETURNS text LANGUAGE sql IMMUTABLE STRICT AS
      $func$
      SELECT public.immutable_unaccent(regdictionary 'unaccent', $1)
      $func$;
    EOSQL

    # new trigger using f_unaccent
    connection.execute(<<-EOSQL)
      CREATE TRIGGER artists_name_tsvector_update BEFORE INSERT OR UPDATE
      OF name ON artists FOR EACH ROW EXECUTE PROCEDURE
      tsvector_update_trigger(
        tsv_name, 'public.f_unaccent(name)', name
      );

      UPDATE artists SET tsv_name = (to_tsvector('public.f_unaccent(name)', name));
    EOSQL

此更新允许用户使用特殊字符进行搜索或不产生相同的结果(例如,“Ønders”和“Onders”搜索查询都返回正确的艺术家。)

注意:我也I18n.transliterate用来本地化传入的查询参数。

更新 - 在运行测试时,我发现我的 UPDATE 代码不正确,因此我不得不更改我的代码以使其正常工作。我会保留以上内容以防它对某人有帮助

使用 @EvanCarroll 的答案https://stackoverflow.com/a/50595181/5261969更新了迁移- 我无法弄清楚如何让更新触发器停止使用 Erwin 的代码进行抱怨。:/

# create extension unaccent
    connection.execute(<<-EOSQL)
      CREATE TEXT SEARCH CONFIGURATION f_unaccent ( COPY = simple );
      ALTER TEXT SEARCH CONFIGURATION f_unaccent
        ALTER MAPPING FOR hword, hword_part, word
        WITH unaccent, simple;
    EOSQL

    # create updated trigger using unaccent for tsv_name
    # update existing tsv_names
    connection.execute(<<-EOSQL)
      CREATE TRIGGER artists_name_tsvector_update BEFORE INSERT OR UPDATE
      OF name ON artists FOR EACH ROW EXECUTE PROCEDURE
      tsvector_update_trigger(
        tsv_name, 'public.f_unaccent', name
      );

      UPDATE artists SET tsv_name = (to_tsvector('public.f_unaccent', name));
    EOSQL
于 2020-02-18T00:11:37.137 回答