As part of the fun, I'm trying to write something similar to pull-syntax
with a meander
Let's say I have db
in this form.
{:ivan {:db/id :ivan, :name "Ivan" :last-name "Ivanov" :friend :petr}
:petr {:db/id :petr, :name "Petr" :last-name "Petrov" :friend :smith}
...
?id {:db/id ?id
?k ?v}}
(pull db [:name {:friend [:name]}] :ivan)
could be presented in this way
(m/find db
{?id {:name ?name
:friend ?friend}
?friend {:name ?friend-name}}
{:name ?name
:friend {:name ?friend-name}})
But how to make a function that would translate pull-syntax
to a meander's query?
For now I have something like that, but I can't do it any simpler and more elegant.
(def eid? (some-fn string? keyword? int?))
(defn pull [db selector entity]
(m/match selector
{:as ?q}
(reduce-kv
(fn [acc k v]
(m/match v
(m/pred vector?)
(assoc acc k (pull db v (get entity k)))))
{}
?q)
[!ks ...]
(reduce
(fn [acc elem]
(m/match elem
(m/pred eid?)
(assoc acc elem (get-in db [entity elem]))
{}
(let [entity' (get-in db [entity])]
(merge acc (pull db elem entity')))))
{}
!ks)))