15

エンティティとそのタイムスタンプに興味があります。基本的に、エンティティの時間順のリストが必要です。

そのために、次の関数を作成しました。

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

無知に根ざしたハックに違いないと私は感じています。

慣用的な Datomic の使用法に詳しい人が介入して、私のパラダイムをアップグレードしてくれるでしょうか?

4

2 に答える 2

9

時間を第一級の原則として名目上理解するデータベースに追加のタイムスタンプを追加するというアイデアに悩まされたため、(Ulrik Sandbergによって概説されたアプローチについて熟考した夜の後)次の関数を進化させました。

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

通常は気にしないため、Datalog ではトランザクション ID 自体へのバインディングを省略するのが慣用的です。この状況では、私たちは非常に重要であり、August Lileaas の言葉を借りれば、「トランザクションをトラバースする」ことを望んでいます (投稿の作成時間を必要とする状況もありますが、このアプリケーションでは、エンティティを注文するにはトランザクション時間で十分です) )。

このアプローチの顕著な欠点は、最近編集されたエントリがリストに追加されることです。そのためには、ブログ標準の投稿履歴を Datomic に「初登場」させるために、後で何かをする必要があります。

要約すると、「投稿」エンティティ ID ごとにトランザクション エンティティ ID をバインドし、後で並べ替えるためにこの関数でトランザクション タイムスタンプを検索しました。

于 2013-09-29T17:47:29.877 に答える
2

これを行うには、トランザクションをトラバースするよりもエレガントな方法はありません。これが、Datomic のトランザクション タイムスタンプに依存するのではなく、タイムスタンプ用に別のドメイン固有の属性を持つことを好む理由です。これが必要な 1 つの例はマージです。たとえば、Wiki があり、2 つの Wiki ページをマージしたいとします。その場合、トランザクションからのタイムスタンプを使用せずに、自分でタイムスタンプを制御したいでしょう。

:created-atと の属性を持つのが好き:changed-atです。新しいエンティティを取引する場合:

[[: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.)]]

次に、更新の場合:

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

そうすれば、エンティティの :created-at 属性を読み取るだけで済みます。エンティティは準備ができており、インデックスで待機しています。

(defmacro find-one-entity
  "Returns entity when query matches, otherwise nil"
  [q db & args]
  `(when-let [eid# (ffirst (d/q ~q ~db ~@args))]
     (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"))
于 2013-09-28T21:41:11.877 に答える