PSQL Процедура обновления триггера обновления базы данных работает. Но процедура вставки не - PullRequest
0 голосов
/ 25 марта 2020

В настоящее время я пытаюсь реализовать Postgres текстовый поиск для моего приложения rails. Мои миграции успешно выполняются с созданием всех таблиц. Одна из моих миграций добавляет триггер для обновления столбца ts_vector (TSV) в моей таблице списков. Он выполняет связку в таблицах и две в промежуточных таблицах. Не уверен, что этот триггер самый эффективный, но он работает, когда вызывается процедурой.

CREATE OR REPLACE FUNCTION update_listings_tsv() RETURNS trigger AS $$
BEGIN
 NEW.tsv := (
   SELECT
     setweight(to_tsvector(l.item_name), 'A') ||
     setweight(to_tsvector(l.description), 'B') ||
     setweight(to_tsvector(categories.name), 'B') ||
     setweight(to_tsvector(sub_categories.name), 'B') ||
     setweight(to_tsvector(sizes.name), 'B') ||
     setweight(to_tsvector(users.username), 'C') ||
     setweight(to_tsvector(string_agg(DISTINCT brands.name, ',')), 'A') ||
     setweight(to_tsvector(string_agg(DISTINCT colours.name, ',')), 'B')


   FROM listings l
   JOIN users ON users.id = l.user_id
   JOIN categories ON categories.id = l.category_id
   JOIN sub_categories ON sub_categories.id = l.sub_category_id
   JOIN sizes ON sizes.id = l.size_id
   JOIN conditions ON conditions.id = l.condition_id


   JOIN brands_listings ON brands_listings.listing_id = l.id
   JOIN brands ON brands.id = brands_listings.brand_id

   JOIN colours_listings ON colours_listings.listing_id = l.id
   JOIN colours ON colours.id = colours_listings.colour_id


   WHERE l.id = NEW.id
   GROUP BY l.id, users.id, categories.id, sub_categories.id, sizes.id, conditions.id
 );
 RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Вот в чем проблема:

Процедура обновления, которая вызывает триггер, работает нормально. Как и предполагалось, когда столбец списка обновляет столбец TSV для этого точного списка также обновляется.

CREATE TRIGGER tsvectorupdateupdate BEFORE UPDATE
ON listings FOR EACH ROW EXECUTE PROCEDURE update_listings_tsv();

Процедура вставки не работает. Я пробовал это ДО и ПОСЛЕ ВСТАВКИ. Я не знаю, где проблема. После сброса db: reset столбец TSV должен быть уже заполнен значением ts_vector.

CREATE TRIGGER tsvectorupdateinsert AFTER INSERT OR UPDATE
ON listings FOR EACH ROW EXECUTE PROCEDURE update_listings_tsv(tsv);

1 Ответ

0 голосов
/ 25 марта 2020

Если вы выполните триггер AFTER, изменить значение будет слишком поздно. Если вы сделаете триггер BEFORE, то будет слишком рано объединяться с (еще не существующей) строкой в ​​таблице «списки». Вам нужно получать новые данные из NEW, а не из «списков».

Я сократил это до минимального значения, добавив в него дополнительные таблицы и столбцы:

CREATE OR REPLACE FUNCTION update_listings_tsv() RETURNS trigger AS $$
BEGIN
 NEW.tsv := (
   SELECT
     setweight(to_tsvector(NEW.item_name), 'A') ||
     setweight(to_tsvector(users.username), 'C')
   FROM users where users.id = NEW.user_id   
 );
 RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER tsvectorupdateinsert BEFORE INSERT OR UPDATE    
ON listings FOR EACH ROW EXECUTE PROCEDURE update_listings_tsv();
...