Fork me on GitHub
#datalog
<
2021-03-25
>
coby16:03:01

Hopefully this is the right place to ask this... I'm struggling with constraining a join across a one-to-many association:

(d/q '[:find (pull ?p [:post/slug
                         {:post/fields
                          [:field/key
                           :field/lang
                           :field/content]}])
         :in $ ?slug ?lang
         :where
         [?p :post/slug ?slug]
         [?p :post/fields ?field]
         [?field :field/lang ?lang]]
       db "child-page" :en)
This returns fields in all languages, not just :en, which is not what I want. I suspect this is because :post/fields is :db.cardinality/many and the join does not constrain them properly. Is this possible or do I need to filter fields after the fact?

Joe Lane16:03:40

You can perform a query + pull in that find clause. Try this:

(d/q '[:find ?slug (pull ?field 
                          [:field/key
                           :field/lang
                           :field/content])
         :in $ ?slug ?lang
         :where
         [?p :post/slug ?slug]
         [?p :post/fields ?field]
         [?field :field/lang ?lang]]
       db "child-page" :en)

coby17:03:11

That works! Thanks!

Joe Lane17:03:14

If you really want a map you could do:

(d/q '[:find ?slug ?key ?lang ?content 
         :in $ ?slug ?lang
         :keys post/slug field/key field/lang field/content
         :where
         [?p :post/slug ?slug]
         [?p :post/fields ?field]
         [?field :field/key ?key]
         [?field :field/lang ?lang]
         [?field :field/content ?content]
       db "child-page" :en)