API Datomic Pull API retrieves only one object

I am having trouble figuring out the pull API. I have two location objects. When I use pull

I only get one.

(ns some-ns.core
  (:require [datomic.api :as d]))

(d/q '[:find ?e 
       :where [?e :location/name]]
     db)
=> #{[17592186045535] [17592186045420]} ; two results

(d/q '[:find [(pull ?e [:db/id
                        :location/name])]
       :where [?e :location/name]]
     db)
=> [{:db/id 17592186045535, :location/name "Some Other Location"}] ; one result

      

I suspect I might be using the wrong pull expression, but I don't see anything terrible.

+3


source to share


3 answers


In the example you provide, you use "single tuple" to find a BOM around a pull expression that only returns one tuple regardless of the number of objects that match the request. You would run into the same problem if you specified a scalar return in find, i.e. With help .

.

(1) The easiest way to fix this is to drop the search spec (this matches the shape of your original query):

(d/q '[:find (pull ?e [:db/id :location/name])
       :where [?e :location/name]]
     db)

      



(2) You can also, as in your own answer, specify a collection in find:

(d/q '[:find [(pull ?e [:db/id :location/name]) ...]
   :where [?e :location/name]]
 db)

      

The main difference is that (1) will return a set of nested maps, while (2) will return vectors of maps.

+3


source


Looks like I was missing ...

.



(d/q '[:find [(pull ?e [:db/id
                        :location/name]) ...]
       :where [?e :location/name]]
     db)
=> [{:db/id 17592186045535, :location/name "Some Other Location"} {:db/id 17592186045420, :location/name "White House"}]

      

+3


source


To avoid subtle mistakes like this, you can try the Duptom Tupelo library.

Instead of using confusing characters like "...", "[]", etc., Tupelo Datomic splits the query syntax into four different functions. Here's a usage example:

  ; If you want just a single attribute as output, you can get a set of values (rather than a set of
  ; tuples) using td/query-set.  As usual, any duplicate values will be discarded.
  (let [names     (td/query-set :let    [$ (live-db)]
                                :find   [?name] ; <- a single attr-val output allows use of td/query-set
                                :where  [ [?eid :person/name ?name] ] )
        cities    (td/query-set :let    [$ (live-db)]
                                :find   [?loc]  ; <- a single attr-val output allows use of td/query-set
                                :where  [ [?eid :location ?loc] ] )

  ]
    (is (= names    #{"Dr No" "James Bond" "M"} ))  ; all names are present, since unique
    (is (= cities   #{"Caribbean" "London"} )))     ; duplicate "London" discarded

      

The API is pull

also supported if that format is better for your problem. Enjoy!

+1


source







All Articles