Fork me on GitHub

Is that possible to get the path between to child? or do I need to structure different way the database?

(def data3
  {:db/ident "top-node"
   :name "hello"
   :children [{:db/ident "A first children"
              :name "A first children"
              :children {:db/ident "A second children"
                         :name "A second children"
                         :children {:db/ident "A third children"
                                   :name "A third children"
                                   :children "no more"}}}
              {:db/ident "B first children"
              :name "first children"
              :children {:db/ident "B second children"
                         :name "B second children"
                         :children {:db/ident "B third children"
                                   :name "B third children"
                                   :children "no more"}}}]})

(def db-uri12 "asami:")
(d/create-database db-uri12)
(def conn12 (d/connect db-uri12))
(def p12 @(d/transact conn12 {:tx-data data3}))
(def db12 (d/db conn12))

(q '[:find  ?a
     :where [?nodeA :name "A third children"]
            [?nodeB :name "B third children"]
            [?nodeA ?a* ?nodeB]]


I would like to get path between NodeA and NodeB. [I can get the path between the top-node and third nodes eg ?p a+ nodeA, but how to possible between nodeA and nodeB?] I’m sorry if that is a trivial thing, I’m new at datalog.


I'm not sure that would be possible. Consider that for that to work you would need to have something like `[?node :some-attribute :tg/node-topNode]` which is simply not there. In other words, what you want is not really transitive – you would need to reverse the 'transitive order' once you reach `top-node`. At least, that's my take on it, but I am far from an expert. Combining the two paths `A->top` and `B->top` you know how to obtain is not good enough?


Okay, I've explored this further. Some general notes. First, note that top-node :tg/owns every node below it, so that there is actually more than one path from top-node to a3. Second, and this is purely subjective, it might help to have some uniformity: top-node's children are an array, which is not true for nodes below. Also note that there is no guaranteed order of results, afaik. Having said all that, you can get all the (unordered) nodes from a3 to b3 like so:

(d/q '[:find ?a
       (or [?a ?path-a* :tg/node-A3]
           [?a ?path-b* :tg/node-B3])
       [?a :children]]
     (d/db conn))

👍 1
👀 1

Sorry for my late reply! Thank you very much your reply, I check it now!!


Yes, that is works in more difficult trees. I used in my tests in wrong way the “OR Constraint”, thank you very much the example. I have an another question:


(q '[:find ?c ?nm
        :where [?nodeA :name "AA third children"]
        [?nodeB :name "BA third children"]
        [?a ?path-a* ?nodeA]
        [?a ?path-b* ?nodeB]
        (or [?b ?path-a* ?nodeA]
            [?b ?path-b* ?nodeB])
        [?b :children]
        (not [?a :children])
        [?c :children]
        [?b :name ?nm]


If I would like to do: (- ?b ?a), so ?b minus ?a nodes, how to possible with asami?


Mainly my question: if I have ?variableA and ?variableB, how to compare or minus (- A B or “The B set does not contain set A.“), is that possible?


(q '[:find ?b ?nm
        :where [?nodeA :name "AA third children"]
        [?nodeB :name "BA third children"]
        (or [?b ?path-a* ?nodeA]
            [?b ?path-b* ?nodeB])
        (not [?b ?path-a* ?nodeA]
             [?b ?path-b* ?nodeB])
        [?b :name ?nm]]


sorry, maybe that is the correct answer [so that is possible]


Hi, @quoll, could you check why this query hangs (does not evaluate):

(def data5
  {:db/id :tg/node-0
   :name "hello"
   :children [{:db/id :tg/node-A1
               :name "A first children"
               :children {:db/id :tg/node-A2
                          :name "A second children"
                          :children {:db/id :tg/node-A3
                                     :name "A third children"
                                     :children "no more"}}}
              {:db/id :tg/node-B1
               :name "first children"
               :children {:db/id :tg/node-B2
                          :name "B second children"
                          :children {:db/id :tg/node-B3
                                     :name "B third children"
                                     :children "no more"}}}]})

(d/transact conn data5)

(d/q '[:find ?common
       [?common :children+ :tg/node-A3]
       [?common :children+ :tg/node-B3]]
     (d/db conn))
I would expect it to return the empty set.


Not online today (on my phone at the moment), but will look at it soon


Absolutely no rush 🙂 Came upon this trying to help sb above.