Как запросить подписку на поле массива в postgresql / sql - PullRequest
0 голосов
/ 07 июня 2018

Мои данные состоят из книг, которым можно назначить несколько категорий (ужасы, драмы, комедии и т. Д.).Пользователи могут подписаться на категорию, и я хочу иметь возможность выполнять постраничные запросы к таблице книг для всех книг, которые имеют указанную категорию.Пример схемы:

CREATE TABLE IF NOT EXISTS books (
  bookid uuid PRIMARY KEY,
  categories uuid[],
  name text,
  author text,
  releasedate timestamp
);

CREATE TABLE IF NOT EXISTS categories (
  categoryid uuid PRIMARY KEY,
  name text
);

CREATE TABLE IF NOT EXISTS users (
  userid uuid PRIMARY KEY,
  name text
);

CREATE TABLE IF NOT EXISTS catsubscribers (
  categoryid uuid REFERENCES categories,
  userid uuid REFERENCES users,
  PRIMARY KEY (categoryid,  userid)
);

CREATE TABLE IF NOT EXIST bookcats (
  bookid uuid REFERENCES books,
  categoryid uuid REFERENCES categories,
  PRIMARY KEY (bookid, categoryid)
);

CREATE OR REPLACE FUNCTION getBooksBySubscribedCategory(me uuid, ofst integer, lim integer)
RETURNS TABLE(bookid uuid, categories uuid[], name text, author text, releasedate timestamp) AS $$
  DECLARE cid RECORD;
  BEGIN
    FOR cid IN (SELECT categoryid FROM catsubscribers WHERE userid = me)
    LOOP
      RETURN QUERY SELECT bks.bookid, bks.categories, bks.name, bks.author, bks.releasedate
      FROM (SELECT bookid, categories, name, author, releasedate FROM books WHERE bookid IN (SELECT bookid FROM bookcats WHERE categoryid = cid ) AS bks
      ORDER BY releasedate DESC
      OFFSET ofst
      LIMIT lim;
    END LOOP;
    RETURN;
  END;
$$ LANGUAGE plpgsql;

Эта функция возвращает массив категорий, на которые подписан пользователь, и циклически перебирает каждую категорию и запрашивает книги в таблице соединений bookcats.Это моя первая попытка грубой силы - уродливая, и я не уверен, что из-за петли правильная нумерация страниц выполняется правильно.Есть ли лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Вам вообще не нужен цикл,

RETURN QUERY 
SELECT bks.bookid, bks.categories, bks.name, bks.author, bks.releasedate
from books bks join bookcats bc on bc.bookid = bks.bookid
join catsubscribers cs on cs.categoryid = bc.categoryid
where cs.userid = me 
group by bks.bookid, bks.categories, bks.name, bks.author, bks.releasedate
limit lim offset ofst
0 голосов
/ 07 июня 2018

OFFSET и LIMIT - классический выбор, но при возникновении проблем с производительностью могут возникнуть и другие соображения: https://use -the-index-luke.com / blog / 2013-07/ pagination-done-the-postgresql-way и https://use -the-index-luke.com / sql / частичные результаты / fetch-next-page - хороший обзор того, какреализовать разбиение по страницам.

В результате необходимо поддерживать внешнее состояние страницы и вместо смещения / предела использовать фильтр WHERE, чтобы просто захватывать соответствующие строки напрямую, фильтруя (в данном случае) по releasedate перед текущей страницей и ограничив ее размером страницы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...