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

zca*_*ate 10 clojure datomic

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

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

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

a2n*_*ade 22

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

Datomic Sc​​hema:博客

查询

请注意,某些关系未显式建模,因为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")
Run Code Online (Sandbox Code Playgroud)

查找用户("john.smith")为其撰写文章的所有类别ID及其名称.

遏制关系

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

执行业务规则

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


clo*_*man 5

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

user ---- * comment
Run Code Online (Sandbox Code Playgroud)

您可以通过让每个注释通过一个属性指向一个用户来选择建模,例如:注释/用户类型:db.type/ref.

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

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

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

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

user * ---- * comment
Run Code Online (Sandbox Code Playgroud)

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

通过这种方式,每个用户可以被多个注释引用,并且每个注释可以引用多个用户.

您可以同样选择在用户而不是评论中引用基数很多.

我希望这足以让你开始:)