Fork me on GitHub
#pathom
<
2021-07-12
>
genekim16:07:09

I was inspired by @wilkerlucio response to someone asking about how to write Pathom queries, and attempted to write one myself. https://clojurians-log.clojureverse.org/pathom/2019-10-22 I found myself immediately wanting to implement it by composing: 1) get all the stories (a query I had already written [:story/all-stories], and then 2) filter them according to the given criteria. I’m delighted I got something working, but for expediency, did something quite ugly — I called parser from inside the resolver, using resolve to avoid the circular dependency, fetching parser/parser and parser/config ,which I had to deref to avoid Don't know how to create ISeq from: clojure.lang.Var error. It works, but I’m guessing there’s a better way to retrieve an EQL query? Or compose resolvers? Thx!

wilkerlucio16:07:59

hello @genekim, for this would be better if you use :story/all-stories as the input in the story-search-resolver, this way you don't have to call the parser from inside

wilkerlucio16:07:50

in Pathom 3 this story is better, because you can do nested inputs on Pathom 3, this means your resolver could have: ::pco/input [{:story/all-stories [:story/id :story/author :story/title]}]

wilkerlucio16:07:13

this way, even if the query is complex (for the nested part under all-stories) Pathom would resolve it first and give the exact input requested

wilkerlucio16:07:34

but if you need the nested details in Pathom 2, them doing a recursive call to the parser is the only way

genekim16:07:13

Holy cow, @wilkerlucio — ::pco/input. That’s amazing. Reading docs on this right now. To confirm my understanding: this would make :story/all-stories available from inside the search resolver, and then I could filter on this?

👍 2
genekim16:07:34

(pathom2, as I’m using Fulcro)

genekim17:07:12

Trying to wrap my head around 1) how to get all the stories in the env. This is the current query that’s working, where search text comes in as a parameter.

['(:search-results/stories {:search/search-query "search text abc!"})])
to…. argh, can’t quite figure out where the :story/all-stories would go? I’m sure it’s not this…
[['(:search-results/stories {:search/search-query "search text abc!"})
  :story/all-stories])
Thx for your help here, @wilkerlucio!

wilkerlucio18:07:24

here is a complete example:

(pc/defresolver all-items []
  {::pc/output [{:all-items [:id :name]}]}
  {:all-items
   [{:id 1 :name "Aa"}
    {:id 2 :name "Ab"}
    {:id 3 :name "Bb"}
    {:id 4 :name "Cc"}]})

(pc/defresolver search [env {:keys [all-items]}]
  {::pc/input  #{:all-items}
   ::pc/output [{:search-results
                 [:id :name]}]}
  (let [search (-> env :ast :params :search)]
    {:search-results
     (filterv #(str/starts-with? (:name %) search) all-items)}))

(comment
  (parser {} ['(:search-results {:search "A"})])
  (parser {} ['(:search-results {:search "B"})]))

wilkerlucio18:07:40

(made in Pathom 2)

wilkerlucio18:07:54

the second argument of the resolver is the input

genekim21:07:04

@wilkerlucio Wow. That is so freaking cool. Absolutely freaking marvelous. THANK YOU!!

genekim21:07:32

The more I study this, the more I feel like I understand Pathom, and the more I’m in awe of it. Freaking awesome, @wilkerlucio!

wilkerlucio21:07:46

one way to look at is like pattern matching, but based on shapes of data (expressed in EQL)

genekim22:07:29

It’s awesome — last question on this, before I call this done! Inspired by your response to that person in 2019, I want to put the search-text and the # of matches into the return result. Is this pc-output shape specified correctly?

(pc/defresolver story-search-resolver [env _]
       {; no ::pc/input
        ::pc/output [:search-results/search-text
                     :search-results/matched
                     {:search-results/stories
                      [:story/id :story/title :story/author :story/content]}]}
       (do
         (log/warn "*** story-search-resolver")
         (handle-search env)))))
The return result from inside the resolver is shown in the screenshot, which looks good! It’s of the shape that I want/expect: But the actual return result from the resolver for this query is… confusing.
['(:search-results/stories {:search/search-query "re-frame"})
     [:search-results/matched :search-results/search-text
      {:search-results/stories [:story/author]}]])

; =>

{:search-results/stories (#:story{:id "K3Y7GLlRfaBDsUWYD0WuXjH/byGbQnwaMWp+PEBoUZw=_16f347d1381:18e306:512e2118",
                                  :author "Arne Brasseur",
                                  :title "Advent 2019 part 23, Full size SVG with Reagent",
                                  :content "XXXXXX"
),
 [:search-results/matched :search-results/search-text #:search-results{:stories [:story/author]}] #:search-results{:matched :search-results/search-text}}
1. I only wanted the story/author to be retrieved, but all the :story fields were retrieved. 2. The search-results/matched | search-text don’t show up as keys in the return map, but are nested inside a vector (or worse. 🙂 The shape I really want is:
#:search-results{:matched 0 :search-text "re-frame" :story #:story{:id :author :content :title}}
Thx again!

wilkerlucio14:07:18

I just took a look, the issue is in you query I believe

wilkerlucio14:07:50

you see. there is no connection in the query between :search-result/stories and the :search-result/matched ...

wilkerlucio14:07:55

its missing a map connecting then

wilkerlucio14:07:15

should be like this:

[{'(:search-results/stories {:search/search-query "re-frame"})
  [:search-results/matched :search-results/search-text
   {:search-results/stories [:story/author]}]}]

genekim18:07:10

@wilkerlucio Holy cow. THANK YOU! (And a huge facepalm, seeing the missed join.). Can’t wait to see this run!