这几个函数能增长一点数据库结构的可读性,简单地省掉一些键盘时间:数据库
;; ============================================== ;; 方便性的处理函数。对于每一个 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}]))