僅供參考,這些都是我目前使用這類任務的一般交易功能(從Clojure的聲明,但如果需要的話應該很容易適應的Java):
[{:db/ident :bsu.fns/replace-to-many-scalars,
:db/doc "Given an entity's lookup ref, a to-many (scalar) attribute, and a list of new values,
yields a transaction that replaces the old values by new ones"
:db/id (d/tempid :db.part/user),
:db/fn (d/function
'{:lang :clojure,
:imports [],
:requires [[datomic.api :as d]],
:params [db entid attr new-vals],
:code (let [old-vals (if-let [e (d/entity db entid)] (get e attr)())
to-remove (remove (set (seq new-vals)) old-vals)]
(concat
(for [ov to-remove] [:db/retract entid attr ov])
(for [nv new-vals] [:db/add entid attr nv]))
)}),
}
{:db/ident :bsu.fns/to-many-retract-all-but,
:db/doc "Given an entity lookup ref, a to-many (entity) attribute, and a list of lookup refs
expands to a transaction which will retract all the [origin `to-many-attr` target] relationships but those for which target is among the `to-spare-lookup-refs`"
:db/id (d/tempid :db.part/user),
:db/fn (d/function
'{:lang :clojure,
:imports [],
:requires [[datomic.api :as d]],
:params [db origin to-many-attr to-spare-lookup-refs],
:code (let [old-targets-ids (d/q '[:find [?t ...] :in $ ?to-many-attr ?origin :where [?origin ?to-many-attr ?t]]
db to-many-attr origin)
to-spare-ids (for [lr to-spare-lookup-refs] (:db/id (d/entity db lr)))
to-delete (->> old-targets-ids (remove (set to-spare-ids)))]
(for [eid to-delete] [:db/retract origin to-many-attr eid])
#_[old-targets-ids to-update-ids to-delete])}),
}]
我不盡管它們都是最佳性能或設計方面的,但它們迄今爲止都在爲我工作。 HTH。
我猜這會產生兩個交易。一個收回所有的價值,另一個收回他們的價值? 我去了另一個創建另一個名字空間的路線,那裏有數組。這樣我只需創建一個新的名稱空間並將ref更改爲新的名稱空間。我不知道這是更快還是更快。 – pompanoSlayer
您正在通過查看兩個數據集合(您在那裏以及您想要在那裏存在什麼)來生成一個事務(「返回生成的事務數據」)。這就是說,我的步驟是冗長的,你可以在檢查後通過例如聲明差異。拉,這可能是一個更好的解決方案。 –
看來,如果我要遵循實體和謂詞的Datomic模型,這將導致我的解決方案VS我的。當我在另一個實體中添加以幫助解決此問題時,它會變得模糊。 – pompanoSlayer