Fork me on GitHub
#datomic
<
2020-10-11
>
joshkh11:10:33

i'm curious if anyone here makes use of recursion in their queries? i tend to find myself thinking "ah, recursion can solve this problem!" but then later i find myself implementing some tricky manipulations outside of the query to get back the results i want. for example, if i want to find the top level post of a nested post, then i have to walk the resulting tree to its maximum depth, which of course is pretty quick, but does not feel elegant.

; the "Third Level" post
(d/q '{:find  [(pull ?post [:post/id :post/text {:post/_posts ...}])]
       :in    [$]
       :where [[?post :post/id #uuid"40b8151d-d5f4-45a6-b78c-67655cdf1583"]]}
     db) 
=>
; and the top post being the most nested
[[{:post/id     #uuid"40b8151d-d5f4-45a6-b78c-67655cdf1583",
   :post/text   "Third Level",
   :post/_posts {:post/id     #uuid"9209c1c6-d553-4632-848a-d9929fd7652a",
                 :post/text   "Second Level",
                 :post/_posts {:post/id   #uuid"0b15be5d-84f2-45d1-8b44-b9928d67f388",
                               :post/text "Top Level"}}}]]

schmee11:10:37

it might be easier to write a rule to get the id of the nested post, and then do a pull on that id

schmee11:10:44

instead of pulling the whole thing

joshkh12:10:22

hmm. i'm not sure how i would write a recursive rule though, e.g. one that unifies on a top level post in the example above

joshkh12:10:13

then again i haven't given it much thought. i'll play around and see what i can come up with. thanks for the advice 🙂

teodorlu12:10:56

If you use recursion without a recursion limit, you open yourself to an infinite loop. Perhaps it makes sense to have a hard-coded recursion limit regardless.

joshkh12:10:40

oh yes, i've been down that road before

steveb8n09:10:24

I have a tree read at the core of my app. It's was tricky to make it perform well and it's still not super fast. I'm using recursive rules. My summary: it's possible but non-trivial