Petrus Theron
Petrus Theron

Reputation: 28866

Passing ?input map as Datomic query argument

How to pass a map as ?input to a Datomic query and destructure the map for matching against facts?

When I run the following query, I get a NullPointerException:

(d/q '[:find ?e
       :where
       :in $ ?input
       [?e :amount ?amount]
       [(:amount ?input) ?amount]]
     (d/db conn)
     {:amount 123.0M})
=> Syntax error (NullPointerException) compiling at ...

However, passing the amount as an input argument, works:

(d/q '[:find ?e
       :where
       :in $ ?amount
       [?e :amount ?amount]
     (d/db conn)
     123.0M)
=> [[1234]]

Upvotes: 1

Views: 346

Answers (1)

Conan
Conan

Reputation: 2358

You can't pass a map into a Datalog query, you're limited to scalars, tuples, collections and relations:

Datomic Query Bindings

If you had a much more complex map than your example and needed to use many values from it, you'd have to destructure it outside (as @Alan Thompson suggested) the query and pass the values in as a tuple:

(let [input-fn (juxt :amount :timestamp :quantity)
      input-data {:timestamp "29/08/2019" :quantity 3 :amount 123.0}
      inputs (input-fn input-data)]
  (d/q '[:find ?e
         :in $ [?amount ?timestamp ?quantity]
         :where
         [?e :amount ?amount]
         [?e :timestamp ?timestamp]
         [?e :quantity ?quantity]]
    (d/db conn)
    inputs))

Upvotes: 2

Related Questions