如何在 Datomic 中表示具有现有 UUID 的实体?

How to represent an entity with an existing UUID in Datomic?

背景

我们有多个通过事件进行通信的服务。许多事件都使用事件中存在的(全局)唯一代理 ID 来引用某个实体。例如 "CustomerRegisteredEvent" (E) 可能包含注册客户的 ID。当使用其他数据库时,我通常可以保留一个 "Customer" 实体,其 ID 对应于 (E) 中存在的 ID(和其他值)。

在 datomic 中,我通常会看到使用 tempid 为新实体生成 id,但我不清楚在事先知道 UUID 的情况下是否应该使用这种方法?

问题

  1. 有没有办法根据事件中的id生成Datomic id?
  2. 如果不是,通常会为 "original"(事件)id 创建一个新属性吗?类似于:

    {:db/id #db/id[:db.part/db] :db/ident :customer/uuid :db/valueType :db.type/string :db/cardinality :db.cardinality/one :db/doc "The original UUID of the customer" :db.install/_attribute :db.part/db}

只需忽略 Datomic :db/id 作为内部细节(就像忽略提交的 Git 散列作为内部细节一样)。在你的问题中使用解决方案 (2),除了你可能想使用内置类型 :db.type/uuid 而不是 string.

您可能也有兴趣查看 the Tupelo-Datomic library,其中包含许多用于与 Datomic 交互的辅助和便利函数。

尽情享受吧!

P.S。不要忽视用于生成半序列 UUID 的 Datomic 函数 d/squuid,这是在 Datomic

中生成 new UUID 的更有效方式

Update:向 Datomic 添加数据有点令人困惑,而且比需要的更复杂。这就是为什么你可以使用 Tupelo-Datomic 来简化整个操作:

(td/transact *conn*
  (td/new-entity { :person/name "James Bond" :location "London"     :weapon/type #{ :weapon/gun :weapon/wit   } } )
  (td/new-entity { :person/name "M"          :location "London"     :weapon/type #{ :weapon/gun :weapon/guile } } )
  (td/new-entity { :person/name "Dr No"      :location "Caribbean"  :weapon/type    :weapon/gun                 } ))

Tupelo-Datomic 为您做的一件事是静默添加样板文件:{:db/id (d/tempid -partition) }