在Datomic中更新具有许多基数的属性的事务

时间:2016-04-01 12:55:14

标签: java datomic

我搜索了两天,但没有看到任何关闭此代码的代码。这是我见过的java中唯一的代码,并不是我想要的。

conn.transact(list(list("db.fn/cas", datomic_id, "attribute you want to update", old value, new value))).get();

我尝试使用旧值中的单个值和新值中的单个值来尝试此代码,但它只是堆叠信息而不是覆盖它。 例如:旧值是鸡,新值是鱼。在交易之后,它是[鸡肉,鱼]而不是我预期的[鱼],鸡将进入存档(历史)。

所以问题是,你如何引用旧的数组值,以及如何将新值赋予数组,以便它像我预期的那样更新如上所述。

我记得在某个地方阅读它只是一系列连接到一个属性的值。如果是这种情况,那是否意味着我必须找到字符串的数据组ID并进行更改?如果它不在新列表中,还必须删除它吗?

2 个答案:

答案 0 :(得分:2)

仅供参考,这些是我目前用于此类任务的通用事务函数(从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。

答案 1 :(得分:0)

如果你需要"最后一次写作获胜"样式一致的解决方案,以替换卡的许多属性的特定实体的所有值,最好的办法是使用transaction function。您可以采取以下方法:

  1. 获取与要收回的所有值的实体+属性匹配的所有数据。
  2. 为所有人生成撤消。
  3. 为所有新值创建添加事务(例如,来自传递的集合)
  4. 删除所有冲突(例如,如果您同时拥有添加和结果的EAV)
  5. 返回生成的交易数据。