Datomic aggregates usage

风流意气都作罢 提交于 2019-12-24 14:13:16

问题


I want to find persons with minimal age with next query

(d/q '[:find ?name (min ?age)
         :in [[?name ?age]]]
       [["John" 20]
        ["Bill" 25]
        ["Jack" 20]
        ["Steve" 28]
        ["Andrew" 30]])

But result is

[["Andrew" 30] ["Bill" 25] ["Jack" 20] ["John" 20] ["Steve" 28]]

How to do that?


回答1:


Instead of chaining the queries together, you could use a subquery (query call from within the query instead of outside of it):

(d/q '[:find ?name ?mage
       :in $
       :where [(datomic.api/q '[:find (min ?age)
                                :where [_ :age ?age]]
                              $) [[?mage]]]
              [?name :age ?mage]]
   [["John" :age 20]
    ["Bill" :age 25]
    ["Jack" :age 20]
    ["Steve" :age 28]
    ["Andrew" :age 30]])

Returns:

#{["John" 20] ["Jack" 20]}



回答2:


This would be a pure Datalog solution

(let [db [["John" 20]
          ["Bill" 25]
          ["Jack" 20]
          ["Steve" 28]
          ["Andrew" 30]]]
  (d/q '[:find ?name ?min-age
         :in $ ?min-age
         :where [?name ?min-age]]
       db
       (ffirst (d/q '[:find (min ?age)
                      :in [[?name ?age]]]
                 db))))

A HAVING clause like in SQL is not part of the query language, but since all queries are executed in the peer, there is no overhead in doing nested queries.




回答3:


You don't need datomic in this case, as you already have in your sequence all the data needed. Use clojure sort instead.

(first (sort-by second [...]))


来源:https://stackoverflow.com/questions/23215114/datomic-aggregates-usage

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!