2013-09-28 7 views
13

Ich interessiere mich für Entitäten und ihre Zeitstempel. Im Wesentlichen möchte ich eine zeitlich sortierte Liste von Entitäten.Letzte Entität von Datomic abrufen

Zu diesem Zweck habe ich die folgenden Funktionen zusammen:

(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))) 

Was ich fühle mich muss ein Hack in Unkenntnis verwurzelt sein.

Würde jemand, der besser mit der idiomatischen Datomic-Verwendung vertraut ist, meine Paradigmen verbessern und aufrüsten?

Antwort

7

ich von der Idee, das Hinzufügen zusätzlicher Zeitstempel in einer Datenbank gestört wurde, die nominell Zeit als First-Class-Prinzip versteht und so (nach einer Nacht auf die Ansätze von Ulrik Sandberg skizzierte von grübelt) entwickelte sich die folgende Funktion:

(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)))) 

Es ist in Datalog idiomatische die Bindung an die Transaktions-ID selbst wegzulassen, wie wir in der Regel kümmern sich nicht. In dieser Situation kümmern wir uns sehr und möchten in den Worten von August Lileaas "die Transaktion durchqueren" (es gibt Situationen, in denen wir die Post-Erstellungszeit wünschen, aber für diese Anwendung reicht die Transaktionszeit für die Bestellung von Entitäten aus).

Ein bemerkenswerter Nachteil dieses Ansatzes ist, dass kürzlich bearbeitete Einträge in der Liste aufgestockt werden. Zu diesem Zweck muss ich später etwas tun, um "Datomic" zum ersten Mal als Post-History zu bloggen.

Zusammenfassend: Ich habe die Transaktion Entity ID per "Post" Entitäts-ID gebunden, und dann nachgeschlagen die Transaktion Zeitstempel mit dieser Funktion für die spätere Sortierung.

+2

Es ist erwähnenswert, dass, AFAIK, gibt Ihnen das den aktuellen Wert von: post/title wurde für die Entität geltend gemacht und nicht, wenn die Entität das letzte Thema einer Transaktion war. – spieden

2

Es gibt nicht wirklich eine elegantere Möglichkeit, dies zu tun als die Transaktionen zu durchlaufen. Aus diesem Grund bevorzuge ich ein separates domänenspezifisches Attribut für Zeitstempel, anstatt mich auf die Transaktionszeitstempel von Datomic zu verlassen. Ein Beispiel, wo dies notwendig ist, ist das Zusammenführen: Nehmen wir an, Sie haben ein Wiki und möchten zwei Wiki-Seiten zusammenführen. In diesem Fall möchten Sie wahrscheinlich den Zeitstempel selbst steuern und nicht den Zeitstempel der Transaktion verwenden. Ich möchte die Attribute :created-at und :changed-at haben. Als ich transact neue Einheiten:

[[:db/add tempid :post/slug "..."] 
[:db/add tempid :post/title "A title"] 
[:db/add tempid :created-at (java.util.Date.)] 
[:db/add tempid :changed-at (java.util.Date.)]] 

Dann gilt für Updates:

[[:db/add post-eid :post/title "An updated title"] 
[:db/add post-eid :changed-at (java.util.Date.)]] 

Auf diese Weise alles, was ich tun muß, ist das Auslesen: erstellt-at-Attribut der Einheit, die bereit sein wird, und im Index warten.

(defmacro find-one-entity 
    "Returns entity when query matches, otherwise nil" 
    [q db & args] 
    `(when-let [eid# (ffirst (d/q ~q ~db [email protected]))] 
    (d/entity ~db eid#))) 

(defn find-post-by-slug 
    [db slug] 
    (find-one-entity 
    '[:find ?e 
     :in $ ?slug 
     :where 
     [?e :post/slug ?slug]] 
    db 
    slug)) 

;; Get timestamp 
(:created-at (find-post-by-slug db "my-post-slug")) 
Verwandte Themen