Использование PG upsert для создания переключателя для действия «Мне нравится» в записи - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь создать функцию "Мне нравится" для сообщений.В моем веб-приложении есть таблица для пользователей и одна для записей.Я создал новую таблицу с именем Like_posts, в которой я сохраняю, кому из пользователей понравился какой пост.

Одно основное ограничение, которое каждому пользователю может понравиться пост только один раз.если пользователь нажимает кнопку «лайк» для записи, которая ему / ей уже понравилась, он переключает / удаляет статус «лайк».

Основная логика:

Если пользователь нажимает «лайк»и
, если like_posts уже содержит строку с user_id и post_id, удалите строку (т. е. пользователь решил не любить ранее понравившийся пост), иначе добавьте новую строку с post_id и user_id.

В настоящее время я запускаю 2 отдельных запроса, сначала чтобы проверить, существует ли строка, а затем мое приложение решает, следует ли его вставить или удалить.Учитывая, что я ожидаю, что «like» - одна из наиболее часто используемых функций, которые изменяют данные БД, я действительно хочу сделать это одним запросом.

Я знаю, что могу сделать это с помощью массивов (liked_by --> user_id в таблице сообщений) но я не хочу идти по этому пути.Развертывание и воссоздание массивов с использованием различных данных не очень производительно, и я действительно не люблю использовать массивы или jsonb в PG (не нравится API).

Я хочу использовать что-то вроде upsert, ноиз того, что я знаю, я могу делать только «О конфликте (один столбец)», пока мне нужно «О конфликте (как col1, так и col2)».

Какие у меня есть варианты и какой будет хорошим способомспроектировать переключение кнопки «Мне нравится» в моей базе данных?

Основываясь на прекрасном совете @Laurenz Albe, я смог улучшить подход.Теперь у меня есть уникальные ограничения на 2 столбца:

CREATE TABLE LIKE_POSTS (
    POST_ID TEXT NOT NULL,
    USER_ID TEXT NOT NULL,
    CREATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UPDATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    DELETED_AT TIMESTAMP,
    CONSTRAINT "Unique_user_and_post_combo" PRIMARY KEY (POST_ID, USER_ID)
);
insert into like_posts (post_id, user_id) values (1,1);

Я до сих пор не уверен, как выполнить действие удаления.Что-то вроде;

insert into like_posts (post_id, user_id) values (1,1) 
returning "ON"
ON CONFLICT ON CONSTRAINT Unique_user_and_post_combo
DO DELETE RETURNING "OFF";

1 Ответ

0 голосов
/ 18 декабря 2018

Теперь у вас есть ограничение первичного ключа, должно быть просто переключить флаг:

INSERT INTO like_posts (post_id, user_id, deleted_at)
   VALUES (1, 1, NULL) 
ON CONFLICT ON CONSTRAINT "Unique_user_and_post_combo"
DO UPDATE SET deleted_at = CASE WHEN deleted_at IS NULL
                                THEN current_timestamp
                           END;

Это предполагает, что вы используете NULL в deleted_at, чтобы показать, что строка активна.

Я рекомендую вам не использовать смешанные имена падежей (как вы использовали для ограничения).

...