我想使用Datomic分区来提高应用的可扩展性。
首先,我首先在事务中创建了一个分区:
{:db/id "communities"
:db/ident :communities}
[:db/add :db.part/db :db.install/partition "communities"]
其次,我在另一个事务中创建了数据库模式:
{:db/ident :person/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db.install/_attribute :communities}
{:db/ident :person/age
:db/valueType :db.type/int
:db/cardinality :db.cardinality/one
:db.install/_attribute :communities}
{:db/ident :person/sibblings
:db/valueType :db.type/int
:db/cardinality :db.cardinality/one
:db.install/_attribute :communities}
以下是一个简单查询的示例:
(d/q '[:find ?name ?age
:where
[?p :person/name ?name]
[?p :person/age ?age]]
db)
当我发出此查询时,出现以下错误:
Unhandled datomic.impl.Exceptions$IllegalArgumentExceptionInfo :db.error/not-an-entity Unable to resolve entity: :person/name {:db/error :db.error/not-an-entity}
当我为每个属性替换:db.install/_attribute :communities
:db.install/_attribute :db.part/db
时,查询工作正常。我对其他所有查询都有同样的问题。
我错过了什么吗?
答案 0 :(得分:3)
用户定义的分区不是替代"链接点"用于用户定义的属性。属性始终通过:db.part/db
属性 1 链接到:db.install/attribute
实体,并且它们始终位于:db.part/db
分区中。
分区允许您确保与某些实体相关的数据通过确保其实体ID在特定范围内分配而在Datomic的索引中紧密相连。如果您的应用可能会同时访问驻留在某个分区中的实体,则可能会提高查询的性能。还可以遍历与驻留在某个分区中的实体相关的数据,而不会遇到不相关的数据(使用seek-datoms
+ EAVT + entid-at
)。
一旦定义分区,使用分区的方法是在创建新实体时将其:db/ident
传递给datomic.api/tempid
(或者您可以将其与#db/id
标记的文字一起使用edn files):
@(d/transact connection
{:db/id (d/tempid :some-partition)
… …})
如果您随后发出了一个查询,该查询恰好提取了与该实体相关的一些EAVT块,那么这些块可能会包含有关同一分区中其他实体的信息(除非该实体在其上声明了足够多的属性以进行填充一个块,我想......但即便如此,你也会在索引树中获取一些相关节点),这样你的对等体就可以从缓存中检索有关它们的信息。
如果您希望从这种类型的地方看到主要好处,那么分区可能值得研究。如果您不确定自己的应用会受益,那就完全没问题。显然,这个功能在野外并没有被广泛使用,实际上新的( - )客户端API目前根本没有公开它。
1 虽然注意到自0.9.5530以来明确的:db.install/_attribute :db.part/db
行是不必要的:Datomic现在推断新引入的实体是来自&#的存在的属性34;属性属性" :db/ident
,:db/valueType
和:db/cardinality
- 这是可能的,因为后两者仅由属性使用 - 并为您添加:db.install/attribute
链接。