我有一个关于 Datomic 更惯用的模式的问题。
假设我们有实体 User
, Post
和 Topic
.Post
可以属于Topic
, User
和其他 Post
(回复)。现在,我应该,
a) 创建一个 :posts
属性,这只是 Post
的列表s,并将其注入(inject)到每个需要引用 Post
的实体中年代?
或者
b) 建立更明确的关系,例如 Post
有一个 :post/author
属性是对用户的引用,也许是 :post/belongs-to
可以引用 Topic
的属性或其他Post
?
观察:
如果我这样做 b ,我似乎得到了更多的语义关系。例如,我可以做 (:post/_author user-entity)
,这比 (:posts user-entity)
更能描述他们的关系的性质(因为,User
具有 :posts
是什么意思?是那些 User
的收藏 Post
s,创作的 Post
s,还是什么?)
的另一个副作用| b 是我可以创建一个新的Post
不改变任何其他实体。如果我这样做 一个 ,我需要创建 Post
并将其插入 :posts
User
的属性,需要两个操作而不是一个。
但是,我有一种感觉,一个 可能是更惯用的方式。例如,似乎更容易看到属性列表 :posts
如果User
随着时间的推移发生了变化,我应该这样做吗?引用资料 :posts
而不是 Post
引用 User
通过:post/author
属性。
什么会更可取,为什么?
最佳答案
您的选项( b )本质上是惯用的,也是进入 datomic 的唯一方法。
所有 datomic 模式仅被编码为属性可以在实体-属性-值 datom (EAV) 的结构中采用的值。
见 http://docs.datomic.com/schema.html - 从文档中提取的一个关键命题是:
Each Datomic database has a schema that describes the set of attributes that can be associated with entities. A schema only defines the characteristics of the attributes themselves. It does not define which attributes can be associated with which entities.
实体本身是高度抽象的(内部只是数字),实体的所有有趣属性都被编码为属性值断言。实体未键入!您可以通过为实体声明的属性创建实体的语义,例如:user/firstname、:post/title、:post/content、:topic/description 等。
这就是为什么你真的想要命名属性的原因。
一个特例是属性类型
:db.type/ref
其中 EAV 中“V”的值本身就是另一个实体。这就是在实体之间创建语义关联的原因。您给每个属性一个“名称”(作为 :db/ident
)来捕获 E<->E 连接的实际含义。所以你可以有一个属性 :db.type/ref
与 :db/ident
“:发布/作者”。请注意,所有
:db.type/ref
属性本质上是双向的,所以如果 Eu
是代表用户的实体,Ep
是表示帖子的实体,那么以下在 datom 创建和查询中是等效的:[Ep :post/author Eu]
[Eu :post/_author Ep]
所有实体关系只是更多的属性断言是非常灵活的。如果您以后想添加收藏帖子的概念,它只是
:db.type/ref
的另一个属性。 .使用 :db/ident
创建它例如 ":user/favorites"并断言预先存在的用户和帖子(具有不同的用户实体作为作者)之间的连接。[aUser :user/favorites somePost]
没有集合值属性的概念,因此您在 ( a ) 中建议的内容在 datomic 中无法正确表达。您将使用查询来聚合帖子。删除后将通过实体本身的撤回来建模。此类撤回的帖子将在数据库历史记录中保持可见。
这确实带来了如何为实体列表指定顺序的挑战。您要么需要使用“自然”排序,例如帖子的日期(在 datomic 事务中捕获或作为帖子的显式属性捕获),要么使用基于属性值的显式排序,例如通过 :post/up-投票数字属性。
如果您需要实体的语义分组,其中“子实体”仅有意义并且仅作为更大事物的一部分存在 - 例如订单中的订单项实体 - 然后查看 datomic components .
关于clojure - 对于此模式,在 Datomic 领域中更惯用的选项是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20068835/