6

我有一个关于 Datomic 更惯用的模式的问题。

假设我们有实体User和。PostTopic

Post可以属于TopicUser其他Post(回复)。现在,我应该,

a) 创建一个:posts属性,它只是一个Posts 列表,并将其注入到每个需要引用多个Posts 的实体中?

或者

b) 建立更明确的关系,例如 aPost有一个:post/author属性是对用户的引用,也许还有一个:post/belongs-to属性可以引用 aTopic或另一个Post

观察:如果我做b,我似乎得到了更多的语义关系。例如,我可以这样做(:post/_author user-entity),这比现在更能描述他们的关系商店的性质(因为,a has(:posts user-entity)是什么意思?那些是s favorited s,authored s,还是什么?)User:postsUserPostPost

b的另一个副作用是我可以在Post不改变任何其他实体的情况下创建一个新实体。如果我做a,我需要创建Post并将其插入到 的:posts属性中User,需要两个操作而不是一个。

但是,我有一种感觉,a可能是更惯用的方式。例如,如果引用而不是通过属性进行引用:posts,如果我想这样做,似乎更容易看到属性列表如何随时间变化。User:postsPostUser:post/author

什么会更可取,为什么?

4

2 回答 2

6

您的选项(b)本质上是惯用且唯一的方式进入 datomic。

所有 datomic 模式仅被编码为属性可以在实体-属性-值 datom (EAV) 的结构中采用的值。

请参阅http://docs.datomic.com/schema.html - 从文档中获取的一个关键命题是:

每个 Datomic 数据库都有一个模式来描述可以与实体关联的属性集。模式只定义属性本身的特征。它没有定义哪些属性可以与哪些实体相关联。

实体本身是高度抽象的(内部只是数字),实体的所有有趣属性都被编码为属性值断言。实体未键入!您可以通过为实体声明的属性来创建实体的语义,例如:用户/名字,:帖子/标题,:帖子/内容,:主题/描述等。这就是您真正想要命名属性的原因。

这种情况的一个特殊情况是属性类型:db.type/ref,其中 EAV 中“V”的值本身就是另一个实体。这就是在实体之间创建语义关联的原因。您给每个属性一个“名称”(作为 a :db/ident)来捕获 E<->E 连接的实际含义。所以你可以有一个:db.type/ref带有:db/ident“:post/author”的属性。

请注意,所有: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

于 2013-12-30T18:13:45.973 回答
0

我认为这主要取决于您的访问模式。如果每次访问可以嵌入其相关帖子的实体时,您确实需要这些帖子,那么嵌入它们( a )是有意义的。如果大多数时候您分别访问它们,那么将它们分开可能会更好(b)。

或者,您可以通过将单独的 Post 实体视为规范实体并将嵌入在各种实体中的实体视为缓存版本来同时执行 ( c )。这样,您需要一个脚本/批处理来在每次更新规范版本时更新嵌入的帖子。由于信息始终存在,这使所有读取变得更容易,但写入更复杂,因为您需要自己保持同步。此外,仅当您可以接受规范版本和嵌入式版本之间的一些不一致并且重新同步的延迟对您而言并不重要时,此模式才可用。

注意:这个建议与 Datomic 没有任何关系,这些是从 NoSQL 世界借来的技术,我绝不是专家。

于 2013-11-21T09:22:53.073 回答