Search code examples
clojuredatomic

Retrieve Most Recent Entity from Datomic


I'm interested in entities and their timestamps. Essentially, I want a time-sorted list of entities.

To that end, I've composed the following functions:

(defn return-posts
  "grabs all posts from Datomic"
  []
  (d/q '[:find ?title ?body ?slug
         :where
         [?e :post/title ?title]
         [?e :post/slug ?slug]
         [?e :post/body ?body]] (d/db connection)))

(defn get-postid-from-slug
  [slug]
  (d/q '[:find ?e
         :in $ ?slug
         :where [?e :post/slug ?slug]] (d/db connection) slug))

(defn get-post-timestamp
  "given an entid, returns the most recent timestamp"
  [entid]
  (->
   (d/q '[:find ?ts
          :in $ ?e
          :where
          [?e _ _ _]
          [?e :db/txInstant ?ts]] (d/db connection) entid)
   (sort)
   (reverse)
   (first)))

Which I feel must be a hack rooted in ignorance.

Would someone more well-versed in idiomatic Datomic usage chime in and upgrade my paradigms?


Solution

  • I was bothered by the idea of adding additional timestamps to a database that nominally understands time as a first-class principle and so (after a night of mulling on the approaches outlined by Ulrik Sandberg) evolved the following function:

    (defn return-posts
      "grabs all posts from Datomic"
      [uri]
      (d/q '[:find ?title ?body ?slug ?ts
             :where
             [?e :post/title ?title ?tx]
             [?e :post/slug ?slug]
             [?e :post/body ?body]
             [?tx :db/txInstant ?ts]] (d/db (d/connect uri))))
    

    It's idiomatic in Datalog to omit the binding to the transaction ID itself as we typically don't care. In this situation, we very definitely care and in the words of August Lileaas, wish to "traverse the transaction" (there are situations in which we'd want the post creation time, but for this application the transaction time will suffice for ordering entities).

    A notable downside to this approach is that recently edited entries will be bumped up in the list. To that end, I'll have to do something later on in order to get their "first appearance" in Datomic for blog-standard post history.

    To summarize: I have bound the transaction entity ID per "post" entity ID, and then looked up the transaction timestamp with this function for later sorting.