Идиоматический способ обмена! или обновить с помощью Datomic

Если я использую атом Clojure для подсчета чего-то (например, голосов), я могу сделать это:

(def votes (atom {}))

(defn vote! [candidate]
  (swap! votes update-in [candidate] (fnil inc 0)))

(vote! "Abraham Lincoln")
(vote! "Abraham Lincoln")
(vote! "Winston Churchill")

votes ;=> {"Abraham Lincoln" 2, "Winston Churchill" 2}

Здесь update-in аккуратно преобразует значение по заданному ключу без необходимости его предварительного поиска.

Как я могу сделать то же самое в Datomic? Я мог бы сделать что-то вроде этого...

(defn vote! [db candidate]
   (let [[e v] (first (q '[:find ?e ?v 
                           :in $ ?candidate 
                           :where [[?e :name ?candidate]
                                   [?e :votes ?v]] db candidate)
     (transact! conn [{:db/id e :votes (inc v)}]))

Но это кажется немного громоздким, когда приходится запускать запрос, возвращать значение, а затем выполнять транзакции с новым значением. Есть ли более идиоматический способ сделать это (например, swap! или update-in)?


person Daniel Neal    schedule 08.06.2014    source источник


Ответы (1)


Мне кажется, что наиболее идиоматично записывать факт голосования, а затем делать запрос на подсчет, когда вы хотите узнать общее количество. В зависимости от потребностей вашего приложения этот подход поддерживает такие вещи, как проверка двойных голосов, изменение/отзыв голосов, подсчет за последние 24 часа, ...

person Randy Hudson    schedule 08.06.2014
comment
Это звучит хорошо. Не могли бы вы немного расширить его? Я пытался выполнить совокупный запрос count. Однако он ничего не возвращает, когда вообще нет голосов. Я думаю, что ищу эквивалент OUTER JOIN... - person Daniel Neal; 08.06.2014
comment
Предположим, что у объекта голосования есть атрибут :vote/for. Затем запрос [:find ?candidate (count ?vote) :where [?vote :vote/for ?candidate]] возвращает набор пар [candidate count] для всех положительных подсчетов голосов. Предположительно, вы знаете пул кандидатов, поэтому вы можете добавить 0 к результату для любых непопулярных кандидатов — часть привлекательности Datomic заключается в том, что вам не нужно иметь всю свою логику в запросе. (Только обязательно проверьте свой запрос, чтобы знать, что отсутствие голосов — единственная причина не получить пару за кандидата.) - person Randy Hudson; 08.06.2014