Fork me on GitHub
#xtdb
<
2023-02-28
>
jmerrifield16:02:47

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!

5
refset17:02:54

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

refset17:02:49

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

nivekuil20:02:23

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

til 2
🙂 2
jmerrifield20:02:22

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

[:xt/id
 {:order/customer [:xt/id :customer/email]}
 :order/created-at
 {:order/customer [:customer/phone]}]
and flatten it into the correct shape. This was the previous implementation:
(defn normalize-pull [p]
  (reduce
   (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
                (hash-map
                 field
                 (normalize-pull
                  (concat
                   (get-in acc [i field])
                   (get val field)))))
         (conj acc val))
       (conj acc val)))
   []
   p))
And now it's just:
(defn normalize-pull [p]
  (reduce #(eql/merge-queries %1 [%2]) [] p))