试图创建一个新的属性,其值是对同一实体的不同属性进行转换的结果。所以,假设我有一个数据库,每个实体都有一个属性。:content
. 我想为每个实体增加一个属性,叫做 :transformed
其值是应用函数 f
到 :content
. 我如何才能习惯性地、有效地进行这项工作?目前我试图通过执行一个事务,将新属性的值赋值给应用于查询该实体原始属性值的函数值来实现。
如果不是很明显的话,我对Datalog和Datascript相当陌生。
(doseq [included-block-ds-id (vec (ds/q '[:find ?id
:where
[?id :block/included true]]
@conn))]
(let [content (first (first (vec (ds/q '[:find ?content
:where
[?included-block-ds-id :block/content ?content]]
@conn))))]
(ds/transact! conn [[:db/add (first included-block-ds-id)
:block/hiccup (block-content->hiccup
conn
content)]])))
总的来说,你的代码是正确的,然而从性能上来说并不是最佳的。你可以使用单个查询来检索所有的id-content对。然后使用 for
. 然后一次性处理完毕。
(let [db @conn
id+content (ds/q '[:find ?id ?content
:where [?id :block/included true]
[?id :block/content ?content]]
db)
tx (for [[id content] id+content]
[:db/add id :block/hiccup (block-content->hiccup db content)])]
(ds/transact! conn tx))
请注意,一般来说,在某个时间点上取一个数据库的不可改变的值,然后基于它进行所有的计算(例如,在传递给 block-content->hiccup
函数)。) 只有当你需要函数来改变db的时候才会传递conn。
在这种情况下,你不需要它,但一般来说,如果你只需要查找单个实体的属性,使用 ds/entity
而不是查询。
(:block/content (d/entity db id))