0

尝试创建一个新属性,其中值是对同一实体的不同属性进行转换的结果。所以,假设我有一个数据库,其中每个实体都有属性: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)]])))
4

1 回答 1

1

一般来说,您的代码是正确的,但在性能方面不是最佳的。您可以使用单个查询来检索所有 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函数)通常是一个好主意。仅当您需要更改数据库的函数时才传递 conn。

在这种情况下你不需要它,但一般来说,如果你只需要在单个实体上查找属性,使用它ds/entity而不是查询更有效:

(:block/content (d/entity db id))
于 2020-05-27T17:17:32.807 回答