gpt4 book ai didi

datomic - 用基数更新值很多

转载 作者:行者123 更新时间:2023-12-04 12:50:35 27 4
gpt4 key购买 nike

我有一个这样的架构:

[{:db/id #db/id[:db.part/db]
:db/ident :person/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "A person's name"
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :person/roles
:db/valueType :db.type/keyword
:db/cardinality :db.cardinality/many
:db/doc "A person's role"
:db.install/_attribute :db.part/db}]

和这样的代码:
;; insert new person
(def new-id (-> (d/transact conn [{:db/id (d/tempid :db.part/user)
:person/name "foo"
:person/roles #{:admin}}])
(:tempids)
(vals)
(first)))

(defn get-roles
[db eid]
(d/q '[:find ?roles .
:in $ ?eid
:where [?eid :user/roles ?roles]]))

(get-roles (d/db conn) new-id) ;; => [:admin]

;; update a person
(d/transact conn [{:db/id new-id
:person/roles #{:client}}])

(get-roles (d/db conn) new-id) ;; => [:admin :client]

似乎它的默认行为是,它只会关联新值。

执行更新事务后,如何获得此结果:
(get-roles (d/db conn) new-id) ;; => [:client]

最佳答案

如果您想要将角色列表“重置”为新值(与仅添加或删除角色的“相对”操作相反的“绝对”操作),则必须使用事务函数来执行差异并收回需要的值。

这是一个基本的通用实现:

{:db/id (d/tempid :db.part/user),
:db/ident :my.fns/reset-to-many,
:db/fn
(d/function
{:lang :clojure,
:requires '[[datomic.api :as d]],
:params '[db e attr new-vals],
:code
'(let [ent (or (d/entity db e)
(throw (ex-info "Entity not found"
{:e e :t (d/basis-t db)})))
entid (:db/id ent)
old-vals (get ent attr)]
(into
[{:db/id (:db/id ent)
;; adding the new values
attr new-vals}]
;; retracting the old values
(comp
(remove (set new-vals))
(map (fn [v]
[:db/retract entid attr v])))
old-vals)
)})}

;; Usage
(d/transact conn [[:my.fns/reset-to-many new-id :person/roles #{:client}]])

关于datomic - 用基数更新值很多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39432061/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com