2

我有一个由问题组成的域模型,每个问题都与许多评论和确认相关联。

我想做一个Datalog 查询,它为每个问题提取一堆内容属性,以及相关的评论和确认的数量,包括这些关系何时为空(例如,某些问题没有评论或没有确认),其中如果返回的计数应为 0。

我已经看到了以下要点,它显示了如何使用“权重”变量(sum ...)并将(or-join)其与“权重”变量结合以在关系为空时获得零计数。

但是,当有 2 个关系时,我看不到如何使这项工作。我尝试了以下方法,但返回的计数不正确:

(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 上问的。

4

2 回答 2

3

总而言之,诀窍是将每个问题、评论和确认视为一个“数据点”,每个计数的“权重”为 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]))]
于 2017-11-21T15:47:58.883 回答
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]]
于 2017-11-21T16:11:51.723 回答