#postgresql #plpgsql #database-trigger
#postgresql #plpgsql #база данных-триггер
Вопрос:
Я пытаюсь разработать систему уведомлений для серверной части приложения / веб-сайта для социальных сетей. Сейчас я сосредоточен на обновлениях статуса. Что я собираюсь сделать, так это поместить триггер в таблицу postgres, связанную с обновлениями статуса, чтобы каждый раз, когда публикуется новое обновление статуса, в мой код отправлялось уведомление.
До сих пор я был в состоянии это сделать. Но дополнительная функция, которую я хотел бы реализовать, — это извлечение всех людей, которые подписаны на пользователя, опубликовавшего обновление статуса, чтобы я мог также отправить им уведомление о том, что человек, на которого они подписаны, опубликовал новое обновление статуса.
Конечно, это можно реализовать, сначала получив уведомление о новом обновлении статуса от postgres, извлекая идентификатор пользователя человека, который его опубликовал, и делая запрос к базе данных, чтобы выяснить, какие пользователи следуют за ними.
Но я подумал, что было бы эффективнее, если бы я не делал запрос, а вместо этого каждый раз, когда postgres хочет отправить мне уведомление о новом обновлении статуса, он также делает запрос, чтобы выяснить, какие пользователи следят за постером обновления статуса, и отправляет эту информацию вместе с уведомлениемдля нового обновления статуса.
Но я не могу понять, как я могу сделать запрос в функции postgres, который зависит от аргумента этой функции, а затем отправить результат этого запроса вместе с аргументом в качестве уведомления.
это то, что я пробовал:
create table example (c1 text, c2 text);
create function notif()
returns trigger as
$$
begin
perform pg_notify('event',row_to_json(new)::text);
return new;
end;
$$ language plpgsql;
create trigger trig after insert
on example
for each row execute procedure notif();
А затем я прослушиваю канал событий из своего кода и получаю вставленную строку. Но я хочу выполнить оператор select на основе новой строки в моей функции notif () и отправить результат с новой строкой в код прослушивания.
Я был бы признателен за любые разъяснения
Спасибо
Комментарии:
1. Я также был бы признателен за разъяснение: как работает уведомление (триггер?
NOTIFY
?) Что вы подразумеваете под «отправкой результата запроса вместе с аргументами функции»? Вы имеете в виду «отправить вместе с результатом функции»? Видите ли, некоторый набросок кода был бы полезен.2. Просто: упакуйте результат запроса в JSON. В чем именно проблема?
3. ну, я не знаю, как это сделать. Я ничего не могу найти в документации postgres, и я тоже ничего не смог найти через Google.
4. Кроме того, в кодах, которые я написал, я не определяю какую-либо новую переменную, и даже функция, которую я создаю, не имеет никаких аргументов. Но каким-то волшебным образом использование
return new
строки возвращается в уведомлении. Как я должен что-то добавить к этому? Как работают переменные в postgres? Все это кажется таким волшебным, и в документации ничего четко не объясняется.5. Тогда вам следует задать разные вопросы, например: «как составить значение JSON из
NEW
и какой-либо результат запроса в триггерной функции?» Функции JSON хорошо документированы, как естьNEW
. Как бы то ни было, вопрос неясен и / или слишком широк.
Ответ №1:
Что-то вроде этого?
CREATE FUNCTION notif()
RETURNS TRIGGER AS $$
DECLARE
data JSONB;
result JSONB;
BEGIN
SELECT json_agg(tmp) -- requires Postgres9.3
INTO data
FROM (
-- your subquery goes here, for example:
SELECT followers.following_user_id
FROM followers
WHERE followers.followed_user_id = NEW.user_id
) tmp;
result := json_build_object('data', data, 'row', row_to_json(NEW));
PERFORM pg_notify('event', result::TEXT);
RETURN NEW;
END;
$$ language plpgsql;
Также из комментариев:
Но каким-то волшебным образом использование
return new
строки возвращается в уведомлении.
Вы неправильно понимаете вещи. Возврат и уведомление — это две разные вещи.
Прежде всего, давайте разберемся с возвратом. Для триггеров AFTER INSERT возвращаемое значение полностью игнорируется:
Возвращаемое значение триггера уровня строки, запущенного ПОСЛЕ или триггера уровня оператора, запущенного ДО или ПОСЛЕ, всегда игнорируется; с таким же успехом оно может быть null .
Возвращаемое значение имеет значение только для триггеров BEFORE. В этом случае вы можете изменить (или даже запретить) строку перед записью в таблицу. Смотрите это: https://www.postgresql.org/docs/9.2/plpgsql-trigger.html Это не имеет никакого отношения к уведомлениям.
Так что насчет уведомлений? Все, что вы получаете от уведомления, — это то, что вы передаете в качестве второго аргумента pg_notify
.Все это довольно хорошо документировано: https://www.postgresql.org/docs/9.0/sql-notify.html
Комментарии:
1. Это здорово, спасибо. Только одно. Я хочу, чтобы как NEW, так и результат подзапроса находились внутри объекта json, который отправляет pg_notify. Как я могу закодировать их в одну переменную?