(This question is more appropriate to the datomic 
group: https://groups.google.com/forum/#!forum/datomic)

Datomic/datalog queries always perform aggregation as a last step so the 
results of aggregation are unavailable to the :where clause. In other 
words, what you want is impossible with a single datalog query.

However, this isn't SQL: the datalog query is run in the peer and all the 
data used for aggregation is transmitted to the peer anyway. Just filter 
over the results yourself with normal Clojure code. There's no advantage to 
expressing everything in a single query like there is in SQL.

(let [db [[:t1 :track/name "foo"]
          [:l1 :lesson/track :t1]
          [:t2 :track/name "bar"]
          [:l2 :lesson/track :t2]
          [:t3 :track/name "baz"]
          [:l3 :lesson/track :t3]
          [:l4 :lesson/track :t3]]]
  (->> (d/q '[:find ?track (count ?lessons)
              :where
              [?t :track/name ?track]
              [?lessons :lesson/track ?t]]
         db)
    (filter (fn [[_ cnt]] (> cnt 1)))))
;=> (["baz" 2])


You can also use two queries: one to get the count per track, another to 
get the track names (but a simple filter is less verbose):

(let [db [[:t1 :track/name "foo"]
          [:l1 :lesson/track :t1]
          [:t2 :track/name "bar"]
          [:l2 :lesson/track :t2]
          [:t3 :track/name "baz"]
          [:l3 :lesson/track :t3]
          [:l4 :lesson/track :t3]]]
  (->>
    (d/q '[:find ?t (count ?lessons)
           :where [?lessons :lesson/track ?t]]
      db)
    (d/q '[:find ?track ?num-lessons
           :in $ [[?t ?num-lessons]]
           :where
           [(> ?num-lessons 1)]
           [?t :track/name ?track]]
         db)))
;=> #{["baz" 2]}



As a side note, be aware that if your track names are not unique you may 
get unexpected results from your current query:

(let [db [[:t1 :track/name "foo"]
          [:l1 :lesson/track :t1]
          [:t2 :track/name "bar"]
          [:l2 :lesson/track :t2]
          [:t3 :track/name "foo"]
          [:l3 :lesson/track :t3]
          [:l4 :lesson/track :t3]]]
  (d/q '[:find ?track (count ?lessons)
         :where
         [?t :track/name ?track]
         [?lessons :lesson/track ?t]]
    db))
;=> [["bar" 1] ["foo" 3]]


This is because the aggregation is done over an unaggregated result *set*  
(i.e. all unique values) and  ?track is the same for multiple ?t. The 
solution is to either include ?t in the :find, or use :with. See the 
Datomic docs more more details: http://docs.datomic.com/query.html#sec-5-17


On Thursday, June 4, 2015 at 6:35:08 AM UTC-5, Wilker wrote:

> Hi, good morning.
>
> I have this query here:
>
> [:find ?track (count ?lessons)
>  :where
>  [?t :track/name ?track]
>  [?lessons :lesson/track ?t]
> ]
>
> A lesson has a track (so a track can be on multiple lessons), and with 
> this query I can return the track names and the number of lessons where 
> this track is being used, all good here.
>
> But I would like to use this count information to filter, and return only 
> tracks that are present in more than one lesson, I tried:
>
> [:find ?track (count ?lessons)
>  :where
>  [?t :track/name ?track]
>  [?lessons :lesson/track ?t]
>  [(> (count ?lessons) 1)]
> ]
>
> Also tried:
>
> [:find ?track ?lc
>  :where
>  [?t :track/name ?track]
>  [?lessons :lesson/track ?t]
>  [(count ?lessons) ?lc]
>  [(> ?lc 1)]
> ]
>
> But I feel like I'm going on the wrong direction... How can I make this 
> query works?
>
> Thanks.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to