Fork me on GitHub

Is there any official (or at least, well-tested) code out there to merge multiple pull queries that might have overlapping fields? e.g. I have these forms: [:xt/id {:order/customer [:xt/id :customer/email]}] and [:order/created-at {:order/customer [:customer/phone]}] and I'd like to run both as a single query so need to turn this into [:xt/id :order/created-at {:order/customer [:xt/id :customer/email :customer/phone]}]. I've built something that works, it's just not very elegant and I worry that there are edge cases I haven't accounted for, hopeful that there's something existing that I could borrow!


Hey @U0EPG0ED7 I've not seen anyone ask about this before, unfortunately, but if you wanted to share the code you have already I'm sure others might be glad to chime in with suggestions for improvement


I have played with deep-merge functions before (in a very different context to pull), but I was similarly never sure whether I was missing edge cases with those also


(eql/merge-queries [:xt/id {:order/customer [:xt/id :customer/email]}] [:order/created-at {:order/customer [:customer/phone]}])`

🙂 1

@U797MAJ8M that's perfect, thanks!! I built a normalize-pull function that will accept a (malformed) query like:

 {:order/customer [:xt/id :customer/email]}
 {:order/customer [:customer/phone]}]
and flatten it into the correct shape. This was the previous implementation:
(defn normalize-pull [p]
   (fn [acc val]
     (if-let [field (and (map? val) (-> val keys first))]
       (if-let [i (find-index (every-pred map? #(contains? % field)) acc)]
         (assoc acc i
                   (get-in acc [i field])
                   (get val field)))))
         (conj acc val))
       (conj acc val)))
And now it's just:
(defn normalize-pull [p]
  (reduce #(eql/merge-queries %1 [%2]) [] p))