【问题标题】:In Datascript, how can I create a new attribute from the value of another?在 Datascript 中,如何从另一个值创建新属性?
【发布时间】:2020-05-26 22:05:14
【问题描述】:

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

【问题讨论】:

    标签: clojurescript datalog datascript


    【解决方案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))
    

    【讨论】:

    • 这更有意义,但是每当我尝试为任何实体查询新创建的:block/hiccup 的数据库时,我仍然会收到 StackOverflowError。这是堆栈跟踪:pastebin.com/wEnmvW6e BTW,使用(:block/hiccup (ds/entity db id)) 时也会出现同样的错误。
    • (block-content->hiccup db content) 返回什么?从堆栈跟踪看来,您以某种方式将数据库放入数据库中
    • 我的天哪...看起来我在调用 (block-content->hiccup conn content) 而不是 (block-content->hiccup content conn)。我想我的大脑看到两者都以“con”开头,然后“是的,那个 con 的东西,把它放在这里”。目前,我只是将该函数用作传入的任何内容的标识函数。但由于我不小心颠倒了参数,“内容”就是整个数据库。 ?‍♂️写下你的:前提条件,伙计们
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多