我有一个由问题组成的域模型,每个问题都与许多评论和肯定相关联。
我想制作一个Datalog query,为每个问题提取一堆内容属性,以及相关评论和肯定的数量,包括这些关系为空时(例如,某些问题没有评论或没有确认),在这种情况下,返回的计数应为0。
我看过以下Gist,其中显示了如何使用(sum ...)
和(or-join)
以及“重量”#39;当关系为空时,变量得到零计数。
然而,当有两种关系时,我不知道如何使这项工作。我尝试了以下方法,但返回的计数不正确:
(def query '[:find (sum ?comment-weight) (sum ?affirmation-weight) ?text ?time ?source-identifier ?q
:with ?uniqueness
:where
[?q :question/text ?text]
[?q :question/time ?time]
[?q :question/source-identifier ?source-identifier]
(or-join [?q ?uniqueness ?comment-weight ?affirmation-weight]
(and [?comment :comment/question ?q]
[?affirmation :affirmation/question ?q]
['((identity ?comment) (identity ?affirmation)) ?uniqueness]
[(ground 1) ?comment-weight]
[(ground 1) ?affirmation-weight])
(and [?comment :comment/question ?q]
[(identity ?comment) ?uniqueness]
[(ground 1) ?comment-weight]
[(ground 0) ?affirmation-weight])
(and [?affirmation :affirmation/question ?q]
[(identity ?affirmation) ?uniqueness]
[(ground 1) ?affirmation-weight]
[(ground 0) ?comment-weight])
(and [(identity ?q) ?uniqueness]
[(ground 0) ?comment-weight]
[(ground 0) ?affirmation-weight]))])
最初询问Clojurians Slack。
答案 0 :(得分:0)
总而言之,诀窍是将每个问题,评论和确认视为一个“数据点”,它具有“权重”和“权重”。每个计数为0或1,并且唯一标识(以便Datalog正确计数,请参阅:with
)。特别是,每个问题对所有计数的权重都为零。
发布的代码几乎是正确的,它只需删除(or-join ...)
的第一个子句,这会导致创建“人工”代码。污染计数的数据点(评论+肯定元组)。
以下内容应该有效:
[:find (sum ?comment-weight) (sum ?affirmation-weight) ?text ?time ?source-identifier ?q
:with ?uniqueness
:where
[?q :question/text ?text]
[?q :question/time ?time]
[?q :question/source-identifier ?source-identifier]
(or-join [?q ?uniqueness ?comment-weight ?affirmation-weight]
(and
[?comment :comment/question ?q]
[(identity ?comment) ?uniqueness]
[(ground 1) ?comment-weight]
[(ground 0) ?affirmation-weight])
(and
[?affirmation :affirmation/question ?q]
[(identity ?affirmation) ?uniqueness]
[(ground 1) ?affirmation-weight]
[(ground 0) ?comment-weight])
(and
[(identity ?q) ?uniqueness]
[(ground 0) ?comment-weight]
[(ground 0) ?affirmation-weight]))]
答案 1 :(得分:0)
您可以在查询中调用任意函数,因此请考虑直接使用datomic.api/datoms
(或子查询或您自己的任意函数)来计算注释和肯定。
使用datomic.api/datoms
:
'[:find ?comment-count ?affirmation-count ?text ?time ?source-identifier ?q
:where
[?q :question/text ?text]
[?q :question/time ?time]
[?q :question/source-identifier ?source-identifier]
[(datomic.api/datoms $ :vaet ?q :comment/question) ?comments]
[(count ?comments) ?comment-count]
[(datomic.api/datoms $ :vaet ?q :affirmation/question) ?affirmations]
[(count ?affirmations) ?affirmation-count]]
或使用子查询:
'[:find ?comment-count ?affirmation-count ?text ?time ?source-identifier ?q
:where
[?q :question/text ?text]
[?q :question/time ?time]
[?q :question/source-identifier ?source-identifier]
[(datomic.api/q [:find (count ?comment) .
:in $ ?q
:where [?comment :comment/question ?q]]
$ ?q) ?comment-count-or-nil]
[(clojure.core/or ?comment-count-or-nil 0) ?comment-count]
[(datomic.api/q [:find (count ?affirmation) .
:in $ ?q
:where [?affirmation :affirmation/question ?q]]
$ ?q) ?affirmation-count-or-nil]
[(clojure.core/or ?affirmation-count-or-nil 0) ?affirmation-count]]
或使用自定义功能:
(defn count-for-question [db question kind]
(let [dseq (case kind
:comments (d/datoms db :vaet question :comment/question)
:affirmations (d/datoms db :vaet question :affirmation/question))]
(reduce (fn [x _] (inc x)) 0 dseq)))
'[:find ?comment-count ?affirmation-count ?text ?time ?source-identifier ?q
:where
[?q :question/text ?text]
[?q :question/time ?time]
[?q :question/source-identifier ?source-identifier]
[(user/count-for-question $ ?q :comments) ?comment-count]
[(user/count-for-question $ ?q :affirmations) ?affirmation-count]]