задача выше была вроде под graphql подвязана, наверное для этого жсон
да, мне на клиента результат жсоном отправлять. пока еще куча сложностей с его получением и формированием, но как решу их, буду смотреть чеширу и что там еще есть для ожсонивания.
а покажи ка пример из чего плоского во что ветвистое тебе нужно переложить?
а то скучно что-то :opieop:
Например из
SELECT
JC_CONTACT.CONTACT_ID,
JC_CONTACT.FIRST_NAME,
POSTS.POST_ID,
POSTS.TITLE,
COMMS.COMM_ID,
COMMS.COMM_TEXT,
CHILDRENS.CHILDREN_ID,
CHILDRENS.FIRST_NAME AS CHILDREN_NAME,
COMM_AUTHORS.CONTACT_ID AS AUTHOR_ID,
COMM_AUTHORS.FIRST_NAME AS AUTHOR_NAME
FROM JC_CONTACT
LEFT OUTER JOIN POSTS ON (JC_CONTACT.contact_id = POSTS.contact_id)
LEFT OUTER JOIN COMMS ON (POSTS.post_id = COMMS.post_id)
LEFT OUTER JOIN CHILDRENS ON (JC_CONTACT.contact_id = CHILDRENS.contact_id)
LEFT OUTER JOIN JC_CONTACT AS COMM_AUTHORS ON (COMM_AUTHORS.contact_id = COMMS.contact_id)
Но сейчас мне подсказали про несколько фичей SQL-я и я буду существенно переделывать и сам формат запросов и соответственно алгоритм их последующей обработки
это графкл такой формы ответ хочет?
ну да. форма ответа задается извне, в виде дерева (потом буду парсить ее из самого граф-куэль запроса), по ней строится текст запроса, получается, результат, обрабатывается моим велосипедом и получается такая иерархическая фигня, которую надо перегнать в жсон и отправить
да ладно. нельзя отдать {:contacts [ {id: 2, :name "Helga", :posts [{:id 4, :name "Post 4}, {...}]}, ... ] ?
запрос кстати кривой походу - кросспродукт всех комментраиев для контакста и всех его детей
я графкл не знаю, но осуждаю считаю, что датомиковские запрос/ответ сильно чётче :opieop:
врядли это то, что предполагалось (или тут наркоманская логика, не знаю)
@misha да там нету формата ответа. с точки зрения апи определяешь огрооомный такой ленвый объект
а потом делаешь запросы вида "дай мне все значения из филда :contacts, для которых вот такойт предикат true, и пожалуйста только вот такие и такие филды давай для них
т.е. эти вот ноды одинаковые - искусственные? (кто-то сам себе палок в колеса наставил)?
ну там не один объект, а несколько (типо REST endpoint), а уж их формат может быть любым. как сам сделаешь
что запрос кривой - не спорю, поэтому и курю сейчас sql, чтобы понять как писать прямые
может пацанам проще такое парсить на юае, кто знает
я обычно такое называю наркоманией, но вообще да, искусственные 😃
@ivana на сколько я знаю, в графкл - запрос повторяет форму ответа, а не наоборот
@ivana правило N0 - не пытатьс все запихнуть в 1 запрос
а насчет что отдать в каком формате - когда решу с sql, буду уже о форматах думать
@anjensan дык графкл - как раз про "запихать всё в 1 запрос", нет разве? (или ты про бд на бекэнде?)
ну если пацанам такое на ui проще писать - знач на ui уже побывали наркоманы 🙂
@anjensan спасибо, а мне сказали что постгресс такой мощный, что можно все в 1 запрос - вот я и пытался сделать так
@misha ну с точки зрения API у тебя может быть один запрос. а уж транслируется он в несколько запросов в БД
по краней мере если у тебя БД реляционная
@malch что там повторяет чью форму - не важно. или я тебя не так понял
ну почти я 😃
а, если про бд, то "да", но как жеж тогда N+1 проблема? база-то мутабельная :kappa:
не, я могу написать наивную реализацию, не вопрос! но тогда действительно будет 100500 запросов к базе на каждый входящий куэль запрос
транзакции
и проблема N+1 это чутка про другое
@ivana важно, от этого зависит, как (rest api) запрос выглядит: выбор приоритета между "удобнее собирать запрос" и "удобнее использовать ответ"
не понял, можешь раскрыть мысль?
в случае с постгрей - вполне себе решается 2мя запросами... SELECT user_id, comment_id FROM ..., & SELECT * FROM comments WHERE id IN $ids
щас кину ссылку про то что ты пишешь, похоже...
@ivana тебе пытаются намекнуть, что юзать такие ответы от апи очень и очень геморно
вот чуваки сделали монстра http://join-monster.readthedocs.io/en/latest/ а вот какие запросы он рождает и какие результаты возвращает http://join-monster.herokuapp.com/graphql?query=%7B%0A%20%20user(id%3A%202)%20%7B%0A%20%20%20%20fullName%0A%20%20%20%20email%0A%20%20%20%20posts%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20body%0A%20%20%20%20%20%20createdAt%0A%20%20%20%20%20%20comments%20%7B%0A%20%20%20%20%20%20%20%20id%0A%20%20%20%20%20%20%20%20body%0A%20%20%20%20%20%20%20%20author%20%7B%0A%20%20%20%20%20%20%20%20%20%20id%0A%20%20%20%20%20%20%20%20%20%20fullName%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D
ну, прикол графкл в том, что ты трамбуешь всё в один апи запрос, который выглядит (структурно-ветвисто) как ответ который ты хочешь получить. Предпочтение там отдается тому, как выглядит ответ, который ты ожидаешь. Типа: то, что получил – сразу легко используешь, а чтоб собрать запрос – надо постараться.
юзать ответы апи геморно - это не моя беда. мне нужно запилить такое апи, а там пусть кто юзает тот и думает что спрашивать.
@ivana норм ответы он возвращает. а у тебя какие монстры
хз тогда : )
я ссылку дал больше про 2 текста sql запросов посмотреть
а у меня то возвращается все нормально, главное дерево правильное и структура, а лишнее убрать - ерунда
¯\(ツ)/¯
не может у тебя возвращаться все правильно как минимум потому, что запрос кривущий 😃
не надо тут рассказывать
:d:
ну запрос кривой, да 🙂 поэтому и говорю, что сейчас думаю что требовать от sql, а потом уже как это обработать и зажсонить
ты выше написал про 2 запроса. тогда у меня будет 2 таблицы их результатов и я буду по ним обеим проходить? Или 1 таблица, а один подзапрос в WHERE или как там в постгрессе
Не смейтесь, я с sql не работал
для затравки
а уж потом можно пробовать запросы писать =\
ох, спасибо, Айболит! сколько всего осиливать... 🙂 Но выбора нет 🙂
ой, хабр, чур-чур!
рандомная ссылка на русском из гугля 🙂
:eew:
@ivana конретно в твоем запрося я хз, ведь не понятно что нужно получить... но судя по всему нужно несколько запросов... вытащить список контактов. потом для них посты. для них комменты... отдельно детей (чтобы это не значило :))
конкретно в этом запросе я пытался впихнуть в одну таблицу ВСЮ иерархию: посты и дети персон, комменты к постам, авторы к комментам - такое вот дерево. И самое забавное, что мой велик прожевывает это, перебирает всю таблицу и строит правильное дерево. Хотя в таблице дофига строк из-за кросспродуктов будет в общем случае, да. Но мой велик пропускает дубли 🙂
там вы ответе ниже собственно заполненных данных есть структура иерархии, как часть этого дерева
пролема что так ты выгребаешь кучу дубликатов. например зачем тебе вытягивать текст всего поста для каждого коммента к нему ?
вообще ведь можно сделать SELECT * FROM JC_CONTACT, POSTS, COMMS, CHILDRENS, а потом все это дело запарсить в clojure. так тоже будет работать 😉
да, я уже напоролся на эти дубликаты. сейчас почитаю вдумчиво что ты написал, и попробую понять.
но мне нужны не все посты, дети, комменты и т.п.! А только те, которые приджойнятся к персонам а на персон условия потом пойдут
ну вот для этого нужно будет делать запросы вида SELECT * FROM POSTS WHERE id in (тут список, полученный на пред этапе из списка постов)
мне тут еще подсказали такую штуку постгресса как array_agg, буду думать чем полезна
а потом в clojure из всего этого (несколько селектов) собирать дерево
хм... ты пишешь точно то же, что делают ребята из джоин монстра по моей ссылке выше. А они (и ты) явно больше знают sql чем я
забей пока - для начала с азами/базой освойся, а потом уже в группировки и array_agg лезь
да и не поможет array_agg в деле вытаскивания / реконструирования древовидной структуры из реляционной БД
а я возлагал на нее надежды... ладно, пойдем по надежному пути, изучать sql и лепить несколько запросов
array_agg вообще - это надстройка постгреса. лучше выучить как это делать на "голом sql"
если честно, то я думал так - эти ребята, что сделали джойн-монстра, делали его не для постгресса, поэтому страдали от отсутствия аррай_эгг() и слепили как могли через несколько запросов 🙂 А мне надо для постгресса и я такой умный щас в один запрос все запишну, раз постгресс умеет много всего дополнительно 🙂
https://hashrocket.com/blog/posts/faster-json-generation-with-postgresql :kappa:
да, я читал про жсон_агг(), но это если тип колонки жсон. Хотя может там можно из всего при выполнении запроса жсон делать.... Спасибо, я посмотрю детальнее.
@misha зачем ты человека смущаешь 🙂
row_to_json
же! :kappa:
@ivana не делай так, пожалуйста 🙂
у меня снова все варианты в мозгах не умещаются 🙂 но еще раз спасибо вам, буду пробовать их все по очереди
🍿
почему не делать так? потому что только на постгрессе будет работать?
@anjensan а почему? медленно будет?
нет. будет даже быстрее на небольших объемах (кложура то медленная) 🙂
постгрес вроде не хипстера пишут, возможно для этого фича и есть
но это по сути запихивание логики внутрь реляционки, что можно делать, если знаешь что делаешь
медленно... мне потом это на клиента слать - а те объемы на которых оно будет медленно, на клинта не пролезут имхо
@misha если у тебя есть дырка^W фича, то не значит что нужно с ней делать все подряд
мне кажется, что такой (хотя бы черновой) вариант - сильно нагляднее всех танцев с кастомными структурами данных и трансформациями. и может быть даже можно мимо кложи ответы отправлять
@ivana у тебя что, ровно 1 клиент ?
@misha нене. наглядность и простота сопровождения - это точно не про генерацию json на стороне постгри
если про апи - то нет, подразумевается что много 🙂
@anjensan ну я не пользуюсь постгресом, и жсоны в sql базах не храню, потому не знаю зачем фича, и ради какого ююзкейса. Но не пользоваться фичей только потому что "непривычно" кому-то – такой себе аргумент
@ivana ну тогда при чем тут объемы. маленький объем помножить на дофига клиентво = загруженная база
@misha если кратко - релаяионку постгрю можно юзать как нереляционную базу
ну тут не факт что мой велик на кложе будет быстрее чем обьработка жсон в постгре
как пример - запихунть полноценный джсон в 1 филд. построить индексы там полноценные и все такое
хз, распарсить глазами 20 строк sql проще будет, чем по 3 неймспейсам кастомные трансформации вычитывать
🤦 🤦 🤦
@anjensan ну я про конкретный случай, ну. что ты сразу фейспалмишь :opieop:
а ничего, что эти 20 строк тебе придется генерить из кложи динамически 😃
чтобы потом это дело в graphql обернуть
ну так и так запросы динамически генерить. только если ответы необработанные никак, то еще их обрабатывать больше после
вообще наверное ты прав да, с другой стороны в этом примере "генерить в кложе" отличается парой токенов row-to-json в этих селектах
всей инфы у меня нет, но сразу отбрасывать этот вариант именно в этом случае - я бы не стал
а это вся инфа - мне надо запилить графкуэль апи для существующей постгресс бд.
ну тут такое дело - генерить json (скажем более правильно - сериализовать. есть же еще bson, yaml, xml и прочее, юзеры апи могут предпочесть другой формат) на базе не прянято
@ivana не знаю я как, что именно значит "запилить графкуэль апи" )
1) это нагружает базу. БД обычно одна и трудно маштабируется, веб серверов много и легко накинуть еще => надо разгружать БД ка можно больше
2) фиг сделаешь пособработку (скажем формат для числа сделать, или там филд переименовать. или еще чего). пихать это в базу - усложняется дебаг и поддержка
ну, тут же можно clojure.data.json/read-string :opieop:
3) структура базы должна соотв структуре твоей бизнес модели. это не всегда получается. но даже если получится... потом фиг поменяешь без жуткой боли
я понял, ты за разделение ответственности, чтобы база занималась только своим (условно) делом. Но если я осилю запилить другой вариант, без жсона в базе и с несколькими запросами...
то лично от меня получишь значок "наркоман" 🙂
и дальше переименовывать и тд. но да, мне "разные мелкие запросы" с этой точки зрения больше нравятся
я и сам иногда страдал... поэтому понимаю как это больно 😉
а разве я его еще не получил за пример моего запроса и ответа выше? 😂
не. ты пока только показал шприц, который я выбир из твоих рук 🙂
😂
не все наркотики одинаково тяжелы :d:
ладно, если серьезно, есть 2 условно приемлемых варианта - несколько запросов и выгребание их в Кложе с заполнением нужной иерархической структуры, и вариант вешать логику компоновки жсонов на базу, так?
а то вы накидываете инфы, для вас она известная, а мне надо сориентироваться 🙂
нет. есть условно 1 вариант - несколько запросов к базе в одной транзакции
то есть мне надо повторить подвиг создателей джойнмонстра по ссылке выше 🙂 понятно 🙂
это сильно меньше подвиг чем альтернатива (если тебе универсальный эндпоинт нужно)
обнадеживаешь, я навскидку почитал и испугался, думал там совсем капец.
но мне еще sql осилить на базовом уровне надо, да
раскладываешь на плоские sql запросы, заворачиваешь в транзакцию
кстати эта, показываю ментору то что наработал на текущий момент (да-да, весь этот наркоманский алгоритм с кривыми запросами 🙂 ), может вы что подскажете по коду - как надо, как нельзя, за что руки оторвать, но только конструктивно - с указанием на что заменить и как правильно 🙂 https://github.com/Ivana-/GraphQL-Postgres-backend-test-1/blob/master/src/project_lein_1/core.clj
как вы скажете по-русски “nil punning” ?
:d:
ждемс
Каламбур ничтозации
кто-нибудь знает, lein для 9 починили?
Кто-нибудь юзал integrant? Как он вообще?