Skip to content

AdStage/pluck-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pluck-api

An small extensible wrapper around Datomic's pull API using multimethods.

Clojars Project

Usage

Datomic's pull API offers a powerfully declarative way to access data stored directly in Datomic. However sometimes we need to access the data in a particular way that is not directly represented in the schema. In this cases the pull API is not sufficient. datomic.api/q does the job but it is not ideal for things like client-side co-located queries in Om.Next.

With the pluck-api we retain the power of client-side queries by extending the pull API with multimethods.

The API is pretty simple. The arguments to adstage.pluck-api/pluck are

  • env a map with stuff like a Datomic db, foreign blob store etc.
  • pattern pull API pattern with extra keys used by the pluck API.
  • eid-or-map if Datomic entity id then datomic.api/pull is used to get the intial result, or you can pass in a map as the initial result.

The API is extended via implemting the adstage.pluck-helper/-pluck multimethod.

Examples

Datalog Query

(require '[adstage.pluck-api :refer [defmethod-cached -pluck pluck]])

Say we want to query some data from a dashboard that is stored in the :db/txInstant datom.

(defmethod -pluck :dashboard/org-time [k {db :db} {eid :db/id}]
  (d/q '[:find  ?created-at .
         :in    $ ?d
         :where [?d :dashboard/organization _ ?org-tx _]
                [?org-tx :db/txInstant ?created-at]]
       db
       eid))
       
(pluck {:db db} [:dashboard/title :dashboard/org-time] dash-eid)
;=> {:dashboard/title "FooBar" :dashboard/org-time #inst "2016-08-20T22:10:26.652-00:00"}

External Blob Store

Datomic is not built for storing large blobs of data, so we often use an external blob store. This also poses a problem for the pull API but we can get around that like so.

(defmethod -pluck :data-source/current-stream
  [k {:keys [db blob-store]} {ds-eid :db/id}]
  (let [data-stream     (-> (d/entity db ds-eid) :data-source/current-stream)
        uuid            (:data-stream/id data-stream)]
    (data-stream/find-by-id blob-store uuid)))
    
(pluck {:db db :blob-store blob-store} [:db/id :data-source/current-stream] data-source-eid)
;=> {:db/id 17592186182360 :data-source/current-stream large-blob}

Caching

We also have a simple macro that will only execute its body if the target key is not passed into the initial result. Useful for when you are querying over a collection of entities and want to pre-fetch some data with a single call to datomic.api/q.

(defmethod-cached -pluck :data-source/fields [k {db :db} pull-result]
  (clojure.edn/read-string (get pull-result :data-source/fields-str)))
  
;; This will not execute the code above.
(pluck {:db db} [:data-source/fields] {:data-source/fields {:foo :bar}})
;=> {:data-source/fields {:foo :bar}}

License

Copyright © 2016 AdStage Distributed under the MIT License (MIT)

About

An extensible wrapper around Datomic's pull API.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •