Size: a a a

NodeUA - JavaScript and Node.js in Ukraine

2020 May 13

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Вадим
поставил. И pgAdmin4 еще поставил. С psql потом разбираться буду, если вдруг понадобится. И драйвер pg для ноды поставил. Хотя не знаю, может sequilize поставить, я еще не решил нужна ли мне ORM. Насколько я понимаю драйвер pg не является ORM, он только конструктор запросов представляет из себя
pg драйвер вроді не має конструктора запитів тому там все треба стрінгом передавати. Knex хороший конструктор запитів. Хз чи тобі потрібна ORM якщо проект малий.
источник

V

Vitaliy in NodeUA - JavaScript and Node.js in Ukraine
Зі слів Тімура - нема ОРМ, які генерують нормальний  sql код)
https://github.com/HowProgrammingWorks/NodejsStarterKit/blob/master/lib/database.js - слой роботи з базою зі стартер кіта
источник

В

Вадим in NodeUA - JavaScript and Node.js in Ukraine
Да я сам пока не знаю, что мне нужно для общения с базой. Проектик из себя представляет просто клон Trello, на фронте реакт, на бэке экспресс, база постгрес. Наверное да, pg будет достаточно
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Vitaliy
Зі слів Тімура - нема ОРМ, які генерують нормальний  sql код)
https://github.com/HowProgrammingWorks/NodejsStarterKit/blob/master/lib/database.js - слой роботи з базою зі стартер кіта
Простіше написати звичайний query builder і самому створити нормальну базу даних. Тоді не буде і негативних JOIN ні проблем з самими запитами :)
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Вадим
Да я сам пока не знаю, что мне нужно для общения с базой. Проектик из себя представляет просто клон Trello, на фронте реакт, на бэке экспресс, база постгрес. Наверное да, pg будет достаточно
Knex хороший квері-білдер. Особливо якщо відносно умов у node потрібно додавати додаткові join, колонки у відповідь і тд.
Наприклад потрібно віддавати карточку із завданням. Ця карточка може віддаватися як і для аноніма так і для користувача. Для користувача буде додаткове поле isLiked.
Knex дозволяє зробити так:
const baseQuery = knex.select('id','all_other_fields').from('card').where({id:card.id});
if(user && user.id){
     baseQuery.modify(queryBuilder => {
       // тут можна багатьма способами написати, але суть та сама
       queryBuilder
         .select('is_liked')
         .leftJoin('card_likes', function joinFunc() {
           this.on('card.id', 'card_likes.card_id').on(
             knex.raw('card_likes.user_id = ?', user.id),
           );
         });
     });
}
const rows = await baseQuery;
І цю штуку можна ускладнювати довго і нудно.
Наприклад заджойнити дві іннер-квері по подвійній on-умові із raw where-умовою, бо використовується якась специфічна функція postgres.
Наприклад baseQuery.where(knex.raw(`query @@ tsvector_title `));
pg + knex - ван лав.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
В інтернеті часто наштовхувався на тексти характеру "не використовуйте Knex".
источник

В

Вадим in NodeUA - JavaScript and Node.js in Ukraine
Andriy Khamurda
Knex хороший квері-білдер. Особливо якщо відносно умов у node потрібно додавати додаткові join, колонки у відповідь і тд.
Наприклад потрібно віддавати карточку із завданням. Ця карточка може віддаватися як і для аноніма так і для користувача. Для користувача буде додаткове поле isLiked.
Knex дозволяє зробити так:
const baseQuery = knex.select('id','all_other_fields').from('card').where({id:card.id});
if(user && user.id){
     baseQuery.modify(queryBuilder => {
       // тут можна багатьма способами написати, але суть та сама
       queryBuilder
         .select('is_liked')
         .leftJoin('card_likes', function joinFunc() {
           this.on('card.id', 'card_likes.card_id').on(
             knex.raw('card_likes.user_id = ?', user.id),
           );
         });
     });
}
const rows = await baseQuery;
І цю штуку можна ускладнювати довго і нудно.
Наприклад заджойнити дві іннер-квері по подвійній on-умові із raw where-умовою, бо використовується якась специфічна функція postgres.
Наприклад baseQuery.where(knex.raw(`query @@ tsvector_title `));
pg + knex - ван лав.
Прочитал, подумал, и теперь хочу knex заюзать) не работал с ним раньше, но выглядит интересно
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Knex має трохи погану документацію, в тому плані що там не описуються всі його можливості. Ну тобто це навіть не сильний мінус. ПРосто самому тяжко зрозуміти що практично кожна його функція приймає кверіБілдери чи інші квері і тд. і це відкриває дуже багато можливостей.
Функціонал для міграцій це взагалі Благодать Господня.
Але свій білдер писати - дорога в нікуди бо це буде той самий knex але з 1% функціоналу. І ще не забувати що не можна інлайнити змінні в кверю, бо це пряма дорога до QSL-інєкцій. Потрібно новіший протокол через драйвер використовувати.
А ще треба менеджити пул самому.
Всі статті які я читав як приклади використовують якийсь дитячий двохрядковий запит. І кнекс там страшніше виглядає. В реальному житті так практично не буває.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Для серйозних запитів потрібно вчити SQL і писати SQL. Тут жоден білдер не дасть потрібного результату. Особливо, якщо вони заточені під щось одне.
Але це вже історія про жадібні запити, коли дуже багато даних з різних таблиць вибираються, коли є дуже багато запитів в базу даних, коли це все треба робити дуже швидко, коли вже йде мова за те, щоб рахувати витрати на доступ до даних і так далі. От тоді це вже серйозний SQL.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
І взагалі, по хорошому, набір полів для вибірки і інші параметри "варто передавати напряму в запит", щоб у випадку зміни назви полів, чи зміни їх вибірки, потрібно було явно визначати, що змінилось і не було чогось такого, як "зайві поля при вибірці" чи ще щось такого характеру. У всьому іншому - якщо запити написані якісно - вони змінюватимуться виключно при зміні структури таблиць чи вибірок.
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Тепер я зрозумів критику. Я просто спочатку вчив SQL, використовував його багато й довго. Потім перейшов вже на квері-білдер. Якось не подумав про зворотній варіант.
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Для мене основний плюс в чому: при певних умовахи у білдер додавати чи задирати якісь компоненти.
Три різні незалежні умови дають 8 варіантів кінцевого запиту. Всіх їх писати стрінгами? Самому писати логіку конкатенації частин запиту? Пробував, нічого доброго з того не вийшло.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Якщо є запити, які вимагають різну кількість чи різні поля загалом, в рамках однієї таблиці - їх можна розділяти. А відносно незалежних умов, то вони працюють як флаги, фільтри чи як? В чому полягає суть цих умов?
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Як розділяти? В окремі запити? В окремі частини запитів які потім самому конкатенувати?
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
Для прикладу, якщо є запит, в якому є три незалежні умови, то можна розділити запит як раз під ці три умови. Так чи інакше у вибірці має бути індекс чи унікальне значення-ідентифікатор, по якому ці дані можна буде мапити згодом.
Таким чином існують три запити, які виконуються в залежності від наявних умов і при наявності id поля додаються в об'єкт, для прикладу.
Це все ускладнюється в залежності від того, чи присутні JOIN чи щось інше, що може ускладнити запит. Це може не працювали, якщо умовою є щось на зразок DISTINCT або щось інше, що має працювати для всіх запитів незалежно від наявності умов. Хоча навіть при цьому можна потім filter дані, після map.
Відповідно з цим, при зміні логіки якоїсь умови доведеться змінювали лише запит, що цієї умови стосується і відповідно додавати поля в цю умову. Сам маппінг при цьому не зміниться, якщо присутні ідентифікатори.
источник
2020 May 14

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Кай
Якщо є запити, які вимагають різну кількість чи різні поля загалом, в рамках однієї таблиці - їх можна розділяти. А відносно незалежних умов, то вони працюють як флаги, фільтри чи як? В чому полягає суть цих умов?
Нехай буде рандомний REST запит. Список товарів.
Цей запит може здійснити неавторизований або авторизований користувач. В залежності від цього необхідно показувати які товари користувач забукмаркав. Це реалізується через джойн на таблицю із списком букмарок користувача.
2 запити.
При запиті може передатися список категорій товару по яких потрібно профільтрувати. Це реалізується через where. Для простоти категорія таблиці товару прописана інтом і фронт передає масив інтів і по ньому фільтрується. Це інша незалежна умова.
Вже на даному етапі ми маємо 4 різні запити.
Потім припустимо ще одна умова із ренджом цін. Від 100 до 1000.
Це вже 8 запитів.
Це не три різні запити а вісім. Тому що йде комбінація умов.
Ну і під кінець є ще поле сортування яке має дефолтне значення.
16 можливих кінцевих станів запиту кожний з яких ти кажеш чистим SQL зреалізувати.

Мапінг це окрема історія він не залежить від створення квері, тобто від того чи кверібілдер чи чистий sql.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
А що додається в самому JOIN в плані товарів?
Тобто це виходить запит для багатьох користувачів, чи для одного? І при цьому виконується JOIN з товарами?
источник

AK

Andriy Khamurda in NodeUA - JavaScript and Node.js in Ukraine
Ну умовно
select item.id, item_field1,item_field2,item_field3, bookmarks.created_at, CASE WHEN bookmarks.user_id IS NOT NULL THEN true ELSE false END AS is_bookmarked
from item
left join bookmark
on item.id = bookmark.item_id
where bookmarks.user_id = ?
Запит для кожного окремого користувача повертає інший стан is_bookmarked.
І залежить від ід користувача яке передали у тому ж JWT.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
А навіщо в такому випадку builder якщо можна обійтись звичайним тернарним оператором для такого?
Є умова "where" - додаєте "where bookmarks.user_id = ?". Тут навіть немає OR/AND.
источник

К

Кай in NodeUA - JavaScript and Node.js in Ukraine
А з JOIN в мене була окрема історія. Свого часу в мене був такий момент, що при JOIN в кожен row додавалися дані, які могли повторюватись і при цьому загальний запит ставав дуже важким для повернення, що "не есть хорошо" і довелось прибирати JOIN і робити окремий запит для того, щоб лише унікальні поля вибирались. В подальшому нормалізував відповідь. Були окремо атрибути і поля з JOIN по типу:
{
 "attributes": [],
 "relationships": {}
}
источник