Задать вопрос
  • Как эффективно использовать 'сервисы' для обращения к БД?

    mayton2019
    @mayton2019
    Bigdata Engineer
    По поводу смыслов. Обычно с БД работают сущностями (entities). Я не специалист в Node и я не знаю
    как у вас принято. Кажется в новых ecma-спецификациях уже ввели понятие класса.

    В данном коде идет проверка на то что email существует. Но полезный эффект - слабый.
    Я-бы сразу возвращал сущность пользователя. Чтоб не бегать потом в базу еще
    раз когда надо поискать имя или дату регистрации. Ну идея такая что
    если вы уж пошли в базу (это сетевой round-trip) то постарайтесь
    за этот трип собрать максимум информации.

    Вот это более рационально
    export const findUserEntityByEmail = async (
      email: string
    ): Promise<User> => {
      try {
        const users = await db
          .query('SELECT * FROM accounts WHERE email = $1', [email])


    Тоже самое относится к выборкам множества строк по множеству ключей.
    Лучше сделать 1 callback который вернет коллекцию чем для коллекции
    ключей дергать один несчастный метод который по штучке что-то достает.

    Еще важне - join. Если соединяете сущности - то соединяйте сразу в БД
    без попыток соединять в приложении. Это кстати еще бонус к компетенции
    в части ACID.

    Тоесть идеальный вариант работы с БД - запросить пакетом всю информацию
    что может потербоваться на ближайшие несколько секунд. Это рациональнее
    чем потом что-то подтягивать.
    Ответ написан
    6 комментариев
  • Как правильно собирать данные с разных таблиц БД?

    erge
    @erge
    Примус починяю
    Для построения такого JSON на SQL вам нужны функции json_agg() / json_build_object(), далее обычные запросы с объединениями и группировкой.

    Пример как собрать JSON author
    SELECT json_build_object(
        'account_id', id,
        'first_name', first_name,
        'last_name', last_name
      ) AS author
      FROM accounts

    post собирается как
    json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )
    при объединении таблиц posts и accounts
    через json_agg собираем в массив
    SELECT json_agg(json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS posts
      FROM posts p
      JOIN accounts a ON a.id = p.author_id

    комментарии аналогично, но с группировкой по постам - post_id
    SELECT json_agg(json_build_object(
        'comment_id', c.id,
        'body', c.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS comments
      FROM comments c
      JOIN accounts a ON a.id = c.author_id
      GROUP BY post_id

    далее объединяем комментарии с постами через post_id = id
    для удобства комментарии вынес в CTE (общее табличное выражение)
    WITH cmts AS (
    SELECT json_agg(json_build_object(
        'comment_id', c.id,
        'body', c.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS comments,
      post_id
      FROM comments c
      JOIN accounts a ON a.id = c.author_id
      GROUP BY post_id
    )
    SELECT json_agg(json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        ),
        'comments', COALESCE(c.comments, '[]')
      )) AS "posts with comments"
      FROM posts p
      JOIN accounts a ON a.id = p.author_id
      LEFT JOIN cmts c ON c.post_id = p.id


    см. пример sqlfiddle
    Ответ написан
    1 комментарий