0

我将所有权作为“项目->所有权->用户”关系传递,以下函数将项目所有者的名称作为文本获取:

CREATE FUNCTION owners_as_text(projects) RETURNS TEXT AS $$
  SELECT trim(both concat_ws(' ', screen_name, first_name, last_name)) FROM users
    INNER JOIN ownerships ON users.id = ownerships.user_id
    WHERE deleted_at IS NULL AND ownable_id = $1.id AND ownable_type = 'Project'
$$ LANGUAGE SQL IMMUTABLE SET search_path = public, pg_temp;

然后使用它来构建一个忽略重音的索引:

CREATE INDEX index_projects_on_owners_as_text
  ON projects
  USING GIN(immutable_unaccent(owners_as_text(projects)) gin_trgm_ops)

当项目更新时,该索引也会更新。但是,当所有者名称更改时,该索引不会被触及,对吧?

在这种情况下,如何强制索引定期更新以赶上?

REINDEX不是一个选项,因为它是锁定的,并且会导致死锁,应该同时发生写入操作。)

4

2 回答 2

1

这个想法是错误的,因为索引是建立在一个实际上不是不可变的函数上的。对于文档:

IMMUTABLE 表示该函数不能修改数据库,并且在给定相同的参数值时总是返回相同的结果;也就是说,它不进行数据库查找或以其他方式使用不直接存在于其参数列表中的信息。

您现在面临的问题来自不正确的假设。

于 2019-01-25T15:16:53.560 回答
0

由于您对 PostgreSQL 撒谎,说该函数IMMUTABLE实际上是STABLE,因此当数据库更改时索引损坏也就不足为奇了。

解决方案是创建这样的索引。

最好不要使用该函数,而是使用具有您要搜索的表达式作为列的视图。然后可以优化使用视图的查询,并且immutable_unaccent(btrim(concat_ws(' ', screen_name, first_name, last_name)))可以使用索引。

欺骗unaccent的波动性可能是可以的......

于 2019-01-25T15:22:12.730 回答