Datomic 的幾個簡單處理函數

這幾個函數能增長一點數據庫結構的可讀性,簡單地省掉一些鍵盤時間:數據庫

;; ==============================================
;; 方便性的處理函數。對於每一個 datomic 程序都有用!

(defn assoc-when [m k v]
  (if v (assoc m k v) m))

(defn attr
  "用縮略形式建立 schema 中的屬性:
   每一個屬性必須有 ident 名稱, type 類型和 doc 文檔.
   可選用 :cardinality 指定數量以及 :unique 指定惟一性"
  [ident type doc
   & {:keys [cardinality unique]
      :or {cardinality :db.cardinality/one
           unique nil}}]
  (-> {:db/ident ident
       :db/valueType type
       :db/doc doc
       :db/cardinality cardinality
       :db.install/_attribute :db.part/db}
      (assoc-when :db/unique unique)))

(defn entities
  "給一組實體 ents 在 part 這個數據庫分區中順序生成臨時 id"
  [part ents]
  (map #(assoc %1 :db/id (d/tempid part %2)) ents (iterate dec -1)))

(defn ensure-db
  "在 uri 上創建一個數據庫, 它的結構爲 schema, 若是有種子數據 seed-data,
   也記入數據庫."
  [uri schema & [seed-data]]
  (d/create-database uri)
  (when-let [conn (d/connect uri)]
    (d/transact conn db-schema)
    (when seed-data
      (d/transact conn seed-data))))

下面這個數據庫函數是傳統的數據庫上必不可少的:ide

(def seq-id
  "Transaction 函數. 給 eid 實體構造的 id-field 設置一個順序的 id. 至關於傳統數據庫的
   sequence 或者自動增加功能.
   要求在數據的種子數據中創建一個實體有 :db/ident (函數中用 next-id 指定),
   這個實體有屬性 next-value 來存儲當前的最後 id 值."
  (d/function {:lang "clojure"
               :params '[db next-id next-value eid id-field]
               :code '(let [val (inc (get (d/entity db next-id) next-value 0))]
                        [{:db/id next-id next-value val}
                         {:db/id eid id-field val}])}))

使用例子

(def db-schema
  "數據庫結構"
  (entities
   :db.part/db
   [(attr :user/name :db.type/string "用戶名" :unique :db.unique/identity)

    (attr :product/id :db.type/string "產品號" :unique :db.unique/identity)
    (attr :product/cashValue :db.type/long "產品的人民幣價值(分)")

    (attr :order/id :db.type/long "訂單號" :unique :db.unique/identity)
    (attr :order/user :db.type/ref "下訂單的用戶")
    (attr :order/product :db.type/ref "訂單所關聯的產品")
    (attr :order/quantity :db.type/long "產品數量")

    (attr :orderId/value :db.type/long "順序中下一個訂單")]))

(def seed-data
  "種子數據"
  (entities
   :db.part/user
   [{:db/ident :orderId/next :orderId/value 10000}
    {:db/ident :nextId
     :db/doc (-> #'seq-id meta :doc)
     :db/fn seq-id}]))
相關文章
相關標籤/搜索