在datomic中建模多个多对多关系

时间:2013-02-06 08:54:06

标签: clojure datomic

也许我还在想sql但是我在编写简单博客的数据模式时遇到了麻烦。 我不太了解:db/cardinality属性及其含义。

就这种类型的系统而言,我们如何建模这些关系

  • 系统支持多个用户
  • 每个用户可能有多个类别
  • 每个用户可能有很多文章
  • 每个类别可能包含许多用户
  • 每个类别可能有很多文章
  • 每篇文章都可能有很多评论
  • 每个评论都有一个用户

2 个答案:

答案 0 :(得分:22)

查看下图并阅读https://gist.github.com/a2ndrade/5651419处的完整代码示例(架构,示例数据和查询)。它应该有助于您了解如何在Datomic中建模数据。

Datomic Schema: Blog

查询

请注意,某些关系未显式建模,因为Datomic中的关系是双向的,因为您可以使用简单的Datalog查询检索其余信息。例如,查询:

(d/q '[:find ?cid ?c
   :in $ ?u
   :where
   [?uid :user/username ?u]
   [?aid :article/category ?cid]
   [?aid :article/author ?uid]
   [?cid :category/name ?c]]
 (d/db conn) "john.smith")

找到用户(“john.smith”)为其撰写文章的所有类别ID及其名称。

遏制关系

一个重要的建模决策是让文章指向评论并将关系标记为:db/isComponent,因为评论本身不应该存在,而是作为文章的一部分。如果文章本身被收回,Datomic将确保收回与文章相关的所有评论。

执行业务规则

如果要强制执行特定于应用程序的一致性规则(例如,文章和评论必须有作者,评论必须具有一定的长度等),您需要使用database functions。它们在交易者内部运行,可以原子地强制执行任意约束,中止不符合它们的交易。

答案 1 :(得分:5)

让我们首先看一下更简单的情况,即在各种实体之间存在一对多的关系(在您的情况下是用户和评论):

user ---- * comment

您可以选择对此进行建模,方法是让每个评论指向一个用户,通过属性:注释/用户 :db.type / ref

这将是一个自然的模型,因为评论最多只能有一个用户。我们说基数最多为1,即。值的计数(在这种情况下是对用户的引用)不能超过1。

这可以在模式中使用:db / cardinality:db.cardinality / one 指定,这实际上是默认值,因此我们不必明确拼写出来。

请注意,由于未键入Datomic实体,因此无法强制实际基数为1,即。任何属性都可以缺席。 (实体通过其实际属性具有隐式类型。维护和解释这些类型完全取决于您的应用程序)

另一方面,如果您希望任何评论适用于多个用户,则您拥有多对多关系:

user * ---- * comment

这可以通过允许属性:comment / user :db / cardinality:db.cardinality / many 来实现,即。允许从用户注释的多个引用。

通过这种方式,每个用户可以被多个评论引用,每个评论可以引用多个用户。

你可以同样选择在用户而不是评论中多次提供基数。

我希望这足以帮助您入门:)