Thank you very much Francis, that was very helpful :)

On Thu, Jun 4, 2015 at 1:21 PM Francis Avila <fav...@breezeehr.com> wrote:

> (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.
>

-- 
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