Mapping a list of datomic ids to entity maps

662 Views Asked by At

When I query for a list of Datomic entities, e.g like in the example below:

'[:find ?e
        :where
        [?e :category/name]]

Usually, I'd like to create a list of maps that represent the full entities, i.e

#{[1234] [2223]} => [{:category/name "x" :db/id 1234}, {:category/name "y" :db/id 2223}]

Here is my approach at the moment, in the form of a helper function.

(defn- db-ids->entity-maps
  "Takes a list of datomic entity ids retrieves and returns
  a list of hydrated entities in the form of a list of maps."
  [db-conn db-ids]
  (->>
    db-ids
    seq
    flatten
    (map #(->>
           %
           ;; id -> lazy entity map
           (d/entity (d/db db-conn))
           ;; realize all values, except for db/id
           d/touch
           (into {:db/id %})))))

Is there a better way?

2

There are 2 best solutions below

2
On BEST ANSWER

With the pull api, this is pretty easy now.

'[:find [(pull ?e [*]) ...] 
  :in $ [[?e] ...] 
  :where [?e]]
2
On

I used to take this approach to save queries to the DB, the code is probably less reusable but it depends on what is more critical in your current scenario. I haven't a Datomic instance configured as I am not working with it right now so it may contain syntax error but I hope you get the idea.

(def query-result '[:find ?cat-name ?id
                :where
                [?cat-name :category/name
                [?id :db/id]])

=>

 #{["x" 1234] ["x" 2223]} 




(defn- describe-values
      "Adds proper keys to the given values."
       [keys-vec query-result]
       (vec (map #(zipmap keys-vec %) query-result)) 



(describe-values [:category/name :db/id] query-result)

=>

[{:db/id 2223, :category/name "x"} {:db/id 1234, :category/name "x"}]