I'm handing ownerships as "Project -> Ownership -> User" relations and the following function gets the project owners' names as text:
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;
This is then used to build an index which ignores accents:
CREATE INDEX index_projects_on_owners_as_text
ON projects
USING GIN(immutable_unaccent(owners_as_text(projects)) gin_trgm_ops)
When the project is updated, this index is updated as well. However, when e.g. an owner name changes, this index won't be touched, right?
How can I force the index to be updated on a regular basis to catch up in that case?
(REINDEX
is not an option since it's locking and will cause deadlocks should write actions happen at the same time.)
Since you lied to PostgreSQL by saying that the function was IMMUTABLE
when it is actually STABLE
, it is unsurprising that the index becomes corrupted when the database changes.
The solution is not to create such an index.
It would be better not to use that function, but a view that has the expression you want to search for as a column. Then a query that uses the view can be optimized, and an index on immutable_unaccent(btrim(concat_ws(' ', screen_name, first_name, last_name)))
can be used.
It is probably OK to cheat about unaccent
's volatility...