DataScript 中的复合元组(Composite Tuples)详解

DataScript 中的复合元组(Composite Tuples)详解

什么是复合元组?

在 DataScript 数据库中,复合元组是一种特殊类型的属性,它由多个标量值组合而成,在内存中表现为 Clojure 向量。复合元组的主要用途包括:

  1. 当领域实体具有多属性组成的键时
  2. 优化需要同时连接同一实体上多个高基数属性的查询

复合元组的工作原理

复合元组完全由 DataScript 自动管理,开发者不需要手动断言或撤销它们。当您断言或撤销构成复合元组的任何一个属性时,DataScript 会自动填充复合值。如果实体的当前值不包含复合元组的所有属性,缺失的属性将被设为 nil。

使用规则

在使用复合元组时,需要遵守以下规则:

  1. 元组属性必须是基数为一(cardinality one)的属性
  2. 元组属性不能引用基数为多(cardinality many)的属性
  3. 元组属性不能引用其他元组属性
  4. 元组属性默认会被索引

实际示例

假设我们有一个包含属性 :a:b:c 的领域模型,并定义了一个复合元组 :a+b+c

{:a+b+c {:db/tupleAttrs [:a :b :c]}}

当我们执行如下事务时:

[{:db/id 1, :a "a", :b "b"}]

实体 1 会自动获得复合属性 :a+b+c

(d/pull db '[*] 1)
; => {:db/id 1, :a "a", :b "b", :a+b+c ["a" "b" nil]}

如果修改属性,元组值会自动更新:

(d/transact! conn
  [{:db/id 1, :a "A", :b "B", :c "c"}])
; => {:db/id 1, :a "A", :b "B", :c "c", :a+b+c ["A" "B" "c"]}

如果移除构成元组的所有属性,元组属性也会被撤销:

(d/transact! conn
  [[:db/add 1 :d "d"]
   [:db/retract 1 :a]
   [:db/retract 1 :b]
   [:db/retract 1 :c]])
; => {:db/id 1, :d "d"}

重要限制

不能直接修改元组属性:

(d/transact! conn
  [{:db/id 1, :a+b+c ["A" "B" "c"]}])
; => 抛出异常:不能直接修改元组属性

索引特性

元组属性会自动建立索引,支持范围查询:

(d/index-range db :a+b+c ["A" "B" "C"] ["a" "b" "c"])
; => [#db/Datom 1 :a+b+c ["a" "b" "c"]]

唯一性约束

可以将元组属性标记为 :db/unique :db.unique/value,实现复合键的唯一性约束:

(def conn (d/create-conn {:a+b {:db/tupleAttrs [:a :b]
                                :db/unique :db.unique/value}}))

这样,虽然单个属性 :a:b 可能不唯一,但它们的组合必须是唯一的:

(d/transact! conn
  [{:db/id 5, :a "A", :b "B"}])
; => 抛出唯一性约束异常

作为标识符使用

如果将元组属性标记为 :db/unique :db.unique/identity,还可以在查找引用中使用:

(def conn (d/create-conn {:a+b {:db/tupleAttrs [:a :b]
                                :db/unique :db.unique/identity}}))

(d/entity (d/db conn) [:a+b ["a" "b"]])
; => 返回对应实体

总结

复合元组在 DataScript 中是一种强大的特性,可以:

  • 自动维护多属性组合值
  • 提供高效的复合键查询
  • 支持唯一性约束
  • 可以作为实体标识符使用

它们的行为与普通属性类似,可以在查找引用、upsert、查询和索引访问等场景中自由使用。理解并合理使用复合元组,可以大大简化某些复杂的数据模型设计。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

劳婵绚Shirley

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值