datomic初体验-用Clojure实现增改查

datomic实现简单的增该查

datomic创建

  • api的引入
 (:require '[datomic.api :as d])
  • 定义url
(def db-url "datomic:mem:dev://localhost:8080/function")

说明:mem指的是创建内存版数据库,数据存储在repl运行期间,项目重启怎数据消失

  • 创建数据库
 (d/create-database db-url)
  • 获取连接,后续插入数据需要
  (def conn (d/connect db-url))
  • 定义schema,数据库存储结构
 (def student-schema [
                       {:db/ident       :student/name
                        :db/valueType   :db.type/string
                        :db/cardinality :db.cardinality/one
                        :db/unique      :db.unique/identity
                        :db/doc         "姓名"}
                       {:db/ident       :student/score
                        :db/valueType   :db.type/ref
                        :db/cardinality :db.cardinality/one
                        :db/isComponent true
                        :db/doc         "成绩"}
                       {:db/ident       :score/yuwen
                        :db/valueType   :db.type/long
                        :db/cardinality :db.cardinality/one
                        :db/doc         "语文成绩"}
                       {:db/ident       :score/math
                        :db/valueType   :db.type/long
                        :db/cardinality :db.cardinality/one
                        :db/doc         "数学成绩"}
                       {:db/ident       :score/english
                        :db/valueType   :db.type/long
                        :db/cardinality :db.cardinality/one
                        :db/doc         "英语成绩"}
                       ])

说明:1、 :db/unique :db.unique/identity设置字段唯一值,如果后续插入数据时,该字段出现相同值,则为修改操作,覆盖之前一条数据的值
2、:db/valueType :db.type/ref设置该字段存储的是entity

  • 插入shcema结构
 (d/transact conn student-schema)

  • 定义基础数据
(def students [{:student/name          "小明"
                  :student/score {:score/yuwen   56
                                  :score/math    76
                                  :score/english 78}}
                 {:student/name          "小强"
                  :student/score {:score/yuwen   67
                                  :score/math    78
                                  :score/english 79}}
                 {:student/name          "小红"
                  :student/score {:score/yuwen   80
                                  :score/math    77
                                  :score/english 90}}])

说明::student/score定义了ref类型,所以需要插入entity

  • 插入基础数据
  (d/transact conn students)

datomic查询操作

  • 查询所有数据
;;查询所有数据,定义查询语句
  (def query-all-data '[:find ?name ?score
                        :where [?e :student/name ?name]
                        [?e :student/score ?score]])
  ;;执行查询语句
  (d/q query-all-data (d/db conn))

结果
查询所有数据结果
说明:因为:student/score定义的ref类型,所以查出来是一个entity,这些显示的是entity的db/id,我们可以根据这个id查出其内容,以小明成绩 17592186045420为例

;; 将结果放入data-xiaoming-map中
  (def data-xiaoming-map (d/entity (d/db conn) 17592186045420))
  ;;从data-xiaoming-map中取出数据
  (get-in data-xiaoming-map [:score/english] )
  (get-in data-xiaoming-map [:score/math] )
  (get-in data-xiaoming-map [:score/yuwen] )

结果:
查询成绩

  • 查询每个成绩
;;查询语句
  (def query-all-data1 '[:find ?name ?yuwen ?math ?english
                         :where [?e :student/name ?name]
                         [?e :student/score ?score]
                         [?score :score/yuwen ?yuwen]
                         [?score :score/math ?math]
                         [?score :score/english ?english]])
  ;;执行
  (d/q  query-all-data1 (d/db conn))

结果
查询结果
这里相当于把每个成绩查出来然后再把数据放到一起,所以结果并不是以插入的格式展示的.

  • 带参数查询,查询小明的成绩
 ;;查询小明成绩
  (def query-xiaoming-data1 '[:find  ?yuwen ?math ?english
                         :where [?e :student/name "小明"]
                         [?e :student/score ?score]
                         [?score :score/yuwen ?yuwen]
                         [?score :score/math ?math]
                         [?score :score/english ?english]])
  ;;执行
  (d/q  query-xiaoming-data1 (d/db conn))

结果
查询小明成绩
第二种查询方式用 :in

 ;;查询小明成绩
  (def query-xiaoming-data2 '[:find  ?name ?yuwen ?math ?english
                              :in $ ?name
                              :where [?e :student/name ?name]
                              [?e :student/score ?score]
                              [?score :score/yuwen ?yuwen]
                              [?score :score/math ?math]
                              [?score :score/english ?english]])
  ;;执行
  (d/q  query-xiaoming-data2 (d/db conn) "小明")

结果
查询小明成绩

  • 其他条件查询,查询语文成绩及格的(大于60)
 ;;查询语文成绩大于60
  (def query-yuwen-data '[:find  ?name ?yuwen ?math ?english
                              :where [?e :student/name ?name]
                              [?e :student/score ?score]
                              [?score :score/yuwen ?yuwen]
                              [(> ?yuwen 60)]
                              [?score :score/math ?math]
                              [?score :score/english ?english]])
  ;;执行
  (d/q  query-yuwen-data (d/db conn))

结果
查询结果

datomic Database Functions功能

详情见官网 Database Function

Database Functions使用示例

  • 说明:在执行数据操作前执行函数,将函数的结果操作到数据
  • 定义schema并初始化数据
 (def db-url "datomic:mem:dev://localhost:8080/function1")
  (d/delete-database db-url)
  (d/create-database db-url)
  (def conn (d/connect db-url))
  (def student-schema [
                       {:db/ident       :name
                        :db/valueType   :db.type/string
                        :db/cardinality :db.cardinality/one
                        :db/unique      :db.unique/identity
                        :db/doc         "姓名"}
                       {:db/ident       :score/yuwen
                        :db/valueType   :db.type/long
                        :db/cardinality :db.cardinality/one
                        :db/doc         "语文成绩"}
                       {:db/ident       :score/math
                        :db/valueType   :db.type/long
                        :db/cardinality :db.cardinality/one
                        :db/doc         "数学成绩"}
                       {:db/ident       :score/english
                        :db/valueType   :db.type/long
                        :db/cardinality :db.cardinality/one
                        :db/doc         "英语成绩"}
                       {:db/ident :addScore
                        :db/fn    #db/fn {:lang   "clojure"
                                          :params [db name type score]
                                          :code   (let [{old-score type} (d/entity db [:name name])
                                                        new-score (+ old-score score)]
                                                    (cond
                                                      (< 100 new-score) [{:name name type 100}]
                                                      (< new-score 0) [{:name name type 0}]
                                                      :else [{:name name type new-score}]))}}
                       ])
  (d/transact conn student-schema)

  (def students [{:name "小明"
                  :score/yuwen 56
                  :score/math 76
                  :score/english 78}
                 {:name "小强"
                  :score/yuwen 67
                  :score/math 78
                  :score/english 79}
                 {:name "小红"
                  :score/yuwen 80
                  :score/math 77
                  :score/english 90}])

  (d/transact conn students)

说明:1、在schema中定义一个增加分数的函数,这个函数的功能就是在指定分数上加减分数(输入负数就减分数),但是加减之后的分数不能超过100,不能低于0分
2、要使函数有效,必须要在schema中定义一个字段 :db/unique :db.unique/identity,上述schema中定义了name为identity。后续修改必须根据name修改

  • 第一次查询成绩
  ;;查询语句
  (def query-all-data '[:find ?name ?yuwen ?math ?english
                        :where [?e :name ?name]
                        [?e :score/yuwen ?yuwen]
                        [?e :score/math ?math]
                        [?e :score/english ?english]])
  ;;执行查询语句
  (d/q query-all-data (d/db conn))

结果
查询结果

  • 给小明英语成绩加20分
(d/transact conn [[:addScore "小明" :score/english  20]])

说明:这里使用了定义到schema里面的函数,执行函数后等到一个结果,然后加此结果放入数据库中

  • 再次查询结果
    查询结果
    这里可以看到 小明的英语成绩已经到加了20到 98了
  • 给小红的英语成绩加30分,那么这里结果应该是100
(d/transact conn [[:addScore "小红" :score/english  30]])

结果
小红成绩
符合预期

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值