Fork me on GitHub
#clojure-russia
<
2017-09-20
>
anjensan09:09:19

@misha @ivana дада. трушные кложуристы используют edn! ведь он принципиально мощнее json-а, и у него есть поддержка в куче либ и приложений!

misha09:09:30

задача выше была вроде под graphql подвязана, наверное для этого жсон

ivana10:09:47

да, мне на клиента результат жсоном отправлять. пока еще куча сложностей с его получением и формированием, но как решу их, буду смотреть чеширу и что там еще есть для ожсонивания.

misha11:09:07

а покажи ка пример из чего плоского во что ветвистое тебе нужно переложить?

misha11:09:17

а то скучно что-то opieop

ivana11:09:37

Например из

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)

ivana11:09:36

Но сейчас мне подсказали про несколько фичей SQL-я и я буду существенно переделывать и сам формат запросов и соответственно алгоритм их последующей обработки

misha12:09:05

это графкл такой формы ответ хочет?

ivana12:09:17

ну да. форма ответа задается извне, в виде дерева (потом буду парсить ее из самого граф-куэль запроса), по ней строится текст запроса, получается, результат, обрабатывается моим велосипедом и получается такая иерархическая фигня, которую надо перегнать в жсон и отправить

anjensan12:09:29

да ладно. нельзя отдать {:contacts [ {id: 2, :name "Helga", :posts [{:id 4, :name "Post 4}, {...}]}, ... ] ?

anjensan12:09:19

запрос кстати кривой походу - кросспродукт всех комментраиев для контакста и всех его детей

misha12:09:52

я графкл не знаю, но осуждаю считаю, что датомиковские запрос/ответ сильно чётче opieop

anjensan12:09:54

врядли это то, что предполагалось (или тут наркоманская логика, не знаю)

anjensan12:09:26

@misha да там нету формата ответа. с точки зрения апи определяешь огрооомный такой ленвый объект

anjensan12:09:00

а потом делаешь запросы вида "дай мне все значения из филда :contacts, для которых вот такойт предикат true, и пожалуйста только вот такие и такие филды давай для них

misha12:09:36

т.е. эти вот ноды одинаковые - искусственные? (кто-то сам себе палок в колеса наставил)?

anjensan12:09:44

ну там не один объект, а несколько (типо REST endpoint), а уж их формат может быть любым. как сам сделаешь

ivana12:09:06

что запрос кривой - не спорю, поэтому и курю сейчас sql, чтобы понять как писать прямые

misha12:09:15

может пацанам проще такое парсить на юае, кто знает

anjensan12:09:16

я обычно такое называю наркоманией, но вообще да, искусственные 😃

misha12:09:51

@ivana на сколько я знаю, в графкл - запрос повторяет форму ответа, а не наоборот

anjensan12:09:54

@ivana правило N0 - не пытатьс все запихнуть в 1 запрос

ivana12:09:58

а насчет что отдать в каком формате - когда решу с sql, буду уже о форматах думать

misha12:09:24

@anjensan дык графкл - как раз про "запихать всё в 1 запрос", нет разве? (или ты про бд на бекэнде?)

anjensan12:09:26

ну если пацанам такое на ui проще писать - знач на ui уже побывали наркоманы 🙂

ivana12:09:42

@anjensan спасибо, а мне сказали что постгресс такой мощный, что можно все в 1 запрос - вот я и пытался сделать так

anjensan12:09:09

@misha ну с точки зрения API у тебя может быть один запрос. а уж транслируется он в несколько запросов в БД

anjensan12:09:19

по краней мере если у тебя БД реляционная

ivana12:09:30

@malch что там повторяет чью форму - не важно. или я тебя не так понял

malch12:09:46

ну почти я 😃

misha12:09:46

а, если про бд, то "да", но как жеж тогда N+1 проблема? база-то мутабельная kappa

ivana12:09:18

не, я могу написать наивную реализацию, не вопрос! но тогда действительно будет 100500 запросов к базе на каждый входящий куэль запрос

anjensan12:09:22

транзакции

anjensan12:09:52

и проблема N+1 это чутка про другое

misha12:09:19

@ivana важно, от этого зависит, как (rest api) запрос выглядит: выбор приоритета между "удобнее собирать запрос" и "удобнее использовать ответ"

ivana12:09:40

не понял, можешь раскрыть мысль?

anjensan12:09:43

в случае с постгрей - вполне себе решается 2мя запросами... SELECT user_id, comment_id FROM ..., & SELECT * FROM comments WHERE id IN $ids

ivana12:09:10

щас кину ссылку про то что ты пишешь, похоже...

anjensan12:09:43

@ivana тебе пытаются намекнуть, что юзать такие ответы от апи очень и очень геморно

misha12:09:28

ну, прикол графкл в том, что ты трамбуешь всё в один апи запрос, который выглядит (структурно-ветвисто) как ответ который ты хочешь получить. Предпочтение там отдается тому, как выглядит ответ, который ты ожидаешь. Типа: то, что получил – сразу легко используешь, а чтоб собрать запрос – надо постараться.

ivana12:09:44

юзать ответы апи геморно - это не моя беда. мне нужно запилить такое апи, а там пусть кто юзает тот и думает что спрашивать.

anjensan12:09:57

@ivana норм ответы он возвращает. а у тебя какие монстры

misha12:09:15

хз тогда : )

ivana12:09:23

я ссылку дал больше про 2 текста sql запросов посмотреть

ivana12:09:49

а у меня то возвращается все нормально, главное дерево правильное и структура, а лишнее убрать - ерунда

misha12:09:16

¯\(ツ)

anjensan12:09:22

не может у тебя возвращаться все правильно как минимум потому, что запрос кривущий 😃

anjensan12:09:26

не надо тут рассказывать

ivana12:09:13

ну запрос кривой, да 🙂 поэтому и говорю, что сейчас думаю что требовать от sql, а потом уже как это обработать и зажсонить

ivana12:09:22

ты выше написал про 2 запроса. тогда у меня будет 2 таблицы их результатов и я буду по ним обеим проходить? Или 1 таблица, а один подзапрос в WHERE или как там в постгрессе

ivana12:09:43

Не смейтесь, я с sql не работал

anjensan12:09:17

для затравки

anjensan12:09:14

а уж потом можно пробовать запросы писать =\

ivana12:09:48

ох, спасибо, Айболит! сколько всего осиливать... 🙂 Но выбора нет 🙂

misha12:09:58

ой, хабр, чур-чур!

anjensan12:09:01

рандомная ссылка на русском из гугля 🙂

anjensan12:09:04

@ivana конретно в твоем запрося я хз, ведь не понятно что нужно получить... но судя по всему нужно несколько запросов... вытащить список контактов. потом для них посты. для них комменты... отдельно детей (чтобы это не значило :))

ivana13:09:25

конкретно в этом запросе я пытался впихнуть в одну таблицу ВСЮ иерархию: посты и дети персон, комменты к постам, авторы к комментам - такое вот дерево. И самое забавное, что мой велик прожевывает это, перебирает всю таблицу и строит правильное дерево. Хотя в таблице дофига строк из-за кросспродуктов будет в общем случае, да. Но мой велик пропускает дубли 🙂

ivana13:09:11

там вы ответе ниже собственно заполненных данных есть структура иерархии, как часть этого дерева

anjensan13:09:40

пролема что так ты выгребаешь кучу дубликатов. например зачем тебе вытягивать текст всего поста для каждого коммента к нему ?

anjensan13:09:32

вообще ведь можно сделать SELECT * FROM JC_CONTACT, POSTS, COMMS, CHILDRENS, а потом все это дело запарсить в clojure. так тоже будет работать 😉

ivana13:09:06

да, я уже напоролся на эти дубликаты. сейчас почитаю вдумчиво что ты написал, и попробую понять.

ivana13:09:05

но мне нужны не все посты, дети, комменты и т.п.! А только те, которые приджойнятся к персонам а на персон условия потом пойдут

anjensan13:09:17

ну вот для этого нужно будет делать запросы вида SELECT * FROM POSTS WHERE id in (тут список, полученный на пред этапе из списка постов)

ivana13:09:36

мне тут еще подсказали такую штуку постгресса как array_agg, буду думать чем полезна

anjensan13:09:50

а потом в clojure из всего этого (несколько селектов) собирать дерево

ivana13:09:42

хм... ты пишешь точно то же, что делают ребята из джоин монстра по моей ссылке выше. А они (и ты) явно больше знают sql чем я

anjensan13:09:50

забей пока - для начала с азами/базой освойся, а потом уже в группировки и array_agg лезь

anjensan13:09:48

да и не поможет array_agg в деле вытаскивания / реконструирования древовидной структуры из реляционной БД

ivana13:09:38

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

anjensan13:09:26

array_agg вообще - это надстройка постгреса. лучше выучить как это делать на "голом sql"

ivana13:09:19

если честно, то я думал так - эти ребята, что сделали джойн-монстра, делали его не для постгресса, поэтому страдали от отсутствия аррай_эгг() и слепили как могли через несколько запросов 🙂 А мне надо для постгресса и я такой умный щас в один запрос все запишну, раз постгресс умеет много всего дополнительно 🙂

ivana13:09:06

да, я читал про жсон_агг(), но это если тип колонки жсон. Хотя может там можно из всего при выполнении запроса жсон делать.... Спасибо, я посмотрю детальнее.

anjensan13:09:08

@misha зачем ты человека смущаешь 🙂

misha13:09:58

row_to_json же! kappa

anjensan13:09:17

@ivana не делай так, пожалуйста 🙂

ivana13:09:22

у меня снова все варианты в мозгах не умещаются 🙂 но еще раз спасибо вам, буду пробовать их все по очереди

ivana13:09:08

почему не делать так? потому что только на постгрессе будет работать?

misha13:09:19

@anjensan а почему? медленно будет?

anjensan13:09:04

нет. будет даже быстрее на небольших объемах (кложура то медленная) 🙂

misha13:09:12

постгрес вроде не хипстера пишут, возможно для этого фича и есть

anjensan13:09:24

но это по сути запихивание логики внутрь реляционки, что можно делать, если знаешь что делаешь

ivana13:09:36

медленно... мне потом это на клиента слать - а те объемы на которых оно будет медленно, на клинта не пролезут имхо

anjensan13:09:06

@misha если у тебя есть дырка^W фича, то не значит что нужно с ней делать все подряд

misha13:09:29

мне кажется, что такой (хотя бы черновой) вариант - сильно нагляднее всех танцев с кастомными структурами данных и трансформациями. и может быть даже можно мимо кложи ответы отправлять

anjensan13:09:35

@ivana у тебя что, ровно 1 клиент ?

anjensan13:09:02

@misha нене. наглядность и простота сопровождения - это точно не про генерацию json на стороне постгри

ivana13:09:14

если про апи - то нет, подразумевается что много 🙂

misha13:09:32

@anjensan ну я не пользуюсь постгресом, и жсоны в sql базах не храню, потому не знаю зачем фича, и ради какого ююзкейса. Но не пользоваться фичей только потому что "непривычно" кому-то – такой себе аргумент

anjensan13:09:42

@ivana ну тогда при чем тут объемы. маленький объем помножить на дофига клиентво = загруженная база

anjensan13:09:12

@misha если кратко - релаяионку постгрю можно юзать как нереляционную базу

ivana13:09:22

ну тут не факт что мой велик на кложе будет быстрее чем обьработка жсон в постгре

anjensan13:09:36

как пример - запихунть полноценный джсон в 1 филд. построить индексы там полноценные и все такое

misha13:09:39

хз, распарсить глазами 20 строк sql проще будет, чем по 3 неймспейсам кастомные трансформации вычитывать

misha13:09:29

@anjensan ну я про конкретный случай, ну. что ты сразу фейспалмишь opieop

anjensan13:09:33

а ничего, что эти 20 строк тебе придется генерить из кложи динамически 😃

anjensan13:09:42

чтобы потом это дело в graphql обернуть

ivana13:09:38

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

misha13:09:59

вообще наверное ты прав да, с другой стороны в этом примере "генерить в кложе" отличается парой токенов row-to-json в этих селектах

misha13:09:55

всей инфы у меня нет, но сразу отбрасывать этот вариант именно в этом случае - я бы не стал

ivana13:09:48

а это вся инфа - мне надо запилить графкуэль апи для существующей постгресс бд.

anjensan13:09:49

ну тут такое дело - генерить json (скажем более правильно - сериализовать. есть же еще bson, yaml, xml и прочее, юзеры апи могут предпочесть другой формат) на базе не прянято

misha13:09:27

@ivana не знаю я как, что именно значит "запилить графкуэль апи" )

anjensan13:09:33

1) это нагружает базу. БД обычно одна и трудно маштабируется, веб серверов много и легко накинуть еще => надо разгружать БД ка можно больше

anjensan13:09:15

2) фиг сделаешь пособработку (скажем формат для числа сделать, или там филд переименовать. или еще чего). пихать это в базу - усложняется дебаг и поддержка

misha13:09:09

ну, тут же можно clojure.data.json/read-string opieop

anjensan13:09:20

3) структура базы должна соотв структуре твоей бизнес модели. это не всегда получается. но даже если получится... потом фиг поменяешь без жуткой боли

ivana13:09:33

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

anjensan13:09:54

то лично от меня получишь значок "наркоман" 🙂

misha13:09:00

и дальше переименовывать и тд. но да, мне "разные мелкие запросы" с этой точки зрения больше нравятся

anjensan13:09:15

я и сам иногда страдал... поэтому понимаю как это больно 😉

ivana13:09:28

а разве я его еще не получил за пример моего запроса и ответа выше? 😂

anjensan13:09:22

не. ты пока только показал шприц, который я выбир из твоих рук 🙂

misha13:09:13

не все наркотики одинаково тяжелы d

ivana13:09:06

ладно, если серьезно, есть 2 условно приемлемых варианта - несколько запросов и выгребание их в Кложе с заполнением нужной иерархической структуры, и вариант вешать логику компоновки жсонов на базу, так?

ivana13:09:00

а то вы накидываете инфы, для вас она известная, а мне надо сориентироваться 🙂

anjensan13:09:18

нет. есть условно 1 вариант - несколько запросов к базе в одной транзакции

ivana13:09:07

то есть мне надо повторить подвиг создателей джойнмонстра по ссылке выше 🙂 понятно 🙂

misha13:09:33

это сильно меньше подвиг чем альтернатива (если тебе универсальный эндпоинт нужно)

ivana13:09:25

обнадеживаешь, я навскидку почитал и испугался, думал там совсем капец.

ivana13:09:46

но мне еще sql осилить на базовом уровне надо, да

misha13:09:51

раскладываешь на плоские sql запросы, заворачиваешь в транзакцию

ivana17:09:02

кстати эта, показываю ментору то что наработал на текущий момент (да-да, весь этот наркоманский алгоритм с кривыми запросами 🙂 ), может вы что подскажете по коду - как надо, как нельзя, за что руки оторвать, но только конструктивно - с указанием на что заменить и как правильно 🙂 https://github.com/Ivana-/GraphQL-Postgres-backend-test-1/blob/master/src/project_lein_1/core.clj

razum2um17:09:01

как вы скажете по-русски “nil punning” ?

dottedmag18:09:31

Каламбур ничтозации

mike_ananev19:09:06

кто-нибудь знает, lein для 9 починили?

dbushenko20:09:52

Кто-нибудь юзал integrant? Как он вообще?