Как в Datascript создать новый атрибут из значения другого?

Попытка создать новый атрибут, значение которого является результатом преобразования другого атрибута той же сущности. Итак, скажем, у меня есть база данных, в которой каждая сущность имеет атрибут: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)]])))

1 ответ

Решение

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

В этом случае он вам не нужен, но в целом, если вам нужно искать атрибуты только для одного объекта, гораздо эффективнее использовать ds/entity вместо запроса:

(:block/content (d/entity db id))
Другие вопросы по тегам