Как в Datascript создать новый атрибут из значения другого? - PullRequest
0 голосов
/ 27 мая 2020

Попытка создать новый атрибут, значение которого является результатом преобразования другого атрибута той же сущности. Итак, скажем, у меня есть база данных, в которой каждая сущность имеет атрибут :content. Я хочу иметь дополнительный атрибут для каждой сущности с именем :transformed, значение которой является результатом применения функции f к :content. Как мне go об этом идиоматично и эффективно? В настоящее время пытаюсь сделать это, выполнив транзакцию и присвоив значение нового атрибута значению функции, примененной к запросу для значения исходного атрибута для этой сущности.

Если это не очевидно, я Я новичок в 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)]])))

1 Ответ

1 голос
/ 27 мая 2020

В целом ваш код правильный, но не с оптимальной производительностью. Вы можете использовать один запрос для получения всех пар id-контент. Затем создайте из них одну транзакцию, используя 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))
...