pathom

:pathom: https://github.com/wilkerlucio/pathom/ & https://pathom3.wsscode.com & https://roamresearch.com/#/app/wsscode
2021-04-26T03:47:35.242100Z

Hi, trying out pathom 3, is this possible? Consider two different APIs providing the same IDs for some data, is there an automatic way of merging two output lists (by ID or composite attributes?): i.e: (defresolver get-names [] {::pco/output {::names [::id ::name]}} {::names [{::id 1 ::name "Foo"} {::id 2 ::name "Bar"}]}) (defresolver get-ages [] {::pco/output {::ages [::id ::age]}} {::ages [{::id 1 ::age 40} {::id 2 ::age 45}]}) I would like to write a query such as below, and have the results grouped by ID automatically, is this possible currently, and if not is my only option creating a third ::people resolver and manually group-by ::id (p.eql/process (pci/register [get-names get-ages]) [{::people [::id ::age ::name]}])

wilkerlucio 2021-04-26T04:36:00.242200Z

hello Chris, it is possible, but the path you are taking here makes things a bit harder because the results are wrapped in lists, its easier if resolvers are at the entity level, so instead of get-names a get-name will be easier, same for get-ages, the simplest path would be something like:

(def names-by-id
  {1 "Foo"
   2 "Bar"})

(def ages-by-id
  {1 40
   2 45})

(pco/defresolver get-name [{::keys [id]}]
  {::name (get names-by-id id ::pco/unknown-value)})

(pco/defresolver get-age [{::keys [id]}]
  {::age (get ages-by-id id ::pco/unknown-value)})

(pco/defresolver all-people []
  {::pco/output [{::people [::id]}]}
  {::people (mapv #(array-map ::id %) (keys names-by-id))})

;; run query

(p.eql/process
  (pci/register [get-name
                 get-age
                 all-people])
  [{::people [::id ::age ::name]}])

2021-04-26T04:43:04.242400Z

Hi Wilker, thanks for the response, the problem is get-names and get-ages are processed responses from an API that I don't control (that only returns items in bulk).

wilkerlucio 2021-04-26T04:44:30.242600Z

there are some tricks you can do in this case, let me write an example for you

wilkerlucio 2021-04-26T04:49:54.242800Z

ok, here is an attribute dance you can do to handle this case:

(defn api-names []
  {:names [{::id 1 ::name "Foo"}
           {::id 2 ::name "Bar"}]})

(defn api-ages []
  {:ages [{::id 1 ::age 40}
          {::id 2 ::age 45}]})

(pco/defresolver names-bulk []
  {::pco/output [::names-index]}
  (let [{:keys [names]} (api-names)]
    {::names-index (->> (coll/index-by ::id names)
                        (coll/map-vals ::name))}))

(pco/defresolver get-name [{::keys [id names-index]}]
  {::name (get names-index id ::pco/unknown-value)})

(pco/defresolver ages-bulk []
  {::pco/output [::ages-index]}
  (let [{:keys [ages]} (api-ages)]
    {::ages-index (->> (coll/index-by ::id ages)
                       (coll/map-vals ::age))}))

(pco/defresolver get-age [{::keys [id ages-index]}]
  {::age (get ages-index id ::pco/unknown-value)})

(pco/defresolver all-people []
  {::pco/output [{::people [::id ::name]}]}
  {::people (:names (api-names))})

;; run query

(p.eql/process
  (pci/register [names-bulk
                 get-name
                 ages-bulk
                 get-age
                 all-people])
  [{::people [::id ::age ::name]}])

wilkerlucio 2021-04-26T04:50:15.243Z

its kinda what I sent before, but now has extra steps to load from a bulk list and index that in mid-process

wilkerlucio 2021-04-26T04:50:29.243200Z

so this way you can access as if they were entity level things

wilkerlucio 2021-04-26T04:52:58.243500Z

(just fixed a bug in the code I sent last)

wilkerlucio 2021-04-26T04:53:18.243700Z

(`coll` is alias for com.wsscode.misc.coll, which is included with Pathom 3)

2021-04-26T05:05:21.244Z

Much appreciated, thanks, also really like using the library in general

🙏 1