Search code examples
datomic

Using a database function in a datomic query


I'm trying to do an 'outer join' in Datomic via the REST API. From https://github.com/Datomic/day-of-datomic/blob/master/tutorial/social_news.clj I have taken the final example:

(defn maybe
  "Returns the set of attr for e, or nil if e does not possess
   any values for attr."
  [db e attr]
  (seq (map :a (d/datoms db :eavt e attr))))

;; find all users 
(q '[:find ?e ?upvote
     :where
     [?e :user/email]
     [(user/maybe $ ?e :user/upVotes) ?upvote]]
   (db conn))

I inserted the maybe function into my database, and it can be queried thus:

[:find ?n ?v :in $ :where [?e ?a ?v] [?a :db/ident :db/fn] [?e :db/ident ?n]]

returns

:maybe  #db/fn{:code "(seq (map :a (d/datoms db :eavt e attr)))", :params [db e attr], :requires [], :imports [], :lang :clojure}

However, I am unable to work out how to call the function in a query. I have an :data/user attribute on some transactions, which I want to get the value for where it exists. Here's the query I'm trying to run; I would like :maybe to be the database function defined above.

[:find ?attr ?v ?when ?who :where
 [17592186045423 ?a ?v ?tx true]
 [?a :db/ident ?attr]
 [(:maybe $ ?tx :data/user) ?who]
 [?tx :db/txInstant ?when]]

I'm pretty sure I'm missing something pretty obvious, but I've been stuck on this for a day now. Thanks for any help!


Solution

  • You need to use d/invoke. So your example would look like this:

    [:find ?attr ?v ?when ?who :where
     [17592186045423 ?a ?v ?tx true]
     [?a :db/ident ?attr]
     [(d/invoke $ :maybe ?tx :data/user) ?who]
     [?tx :db/txInstant ?when]]