Использование агрегатов Datomic

Я хочу найти людей с минимальным возрастом с помощью следующего запроса

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

Но результат

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

Как это сделать?


person Nawa    schedule 22.04.2014    source источник


Ответы (3)


Вместо объединения запросов вместе вы можете использовать подзапрос (вызов запроса внутри запроса, а не за его пределами):

(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]])

Возвращает:

#{["John" 20] ["Jack" 20]}
person Ben Kamphaus    schedule 11.06.2015

Это было бы чистое решение Datalog

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

Предложение HAVING, как и в SQL, не является частью языка запросов, но, поскольку все запросы выполняются в одноранговом узле, выполнение вложенных запросов не требует дополнительных затрат.

person stijnopheide    schedule 02.05.2014
comment
Я сделал то же самое в качестве решения. Но 2 запроса это плохо, на мой взгляд. Реально ли это сделать одним чистым запросом? - person Nawa; 03.05.2014
comment
Это зависит от того, что вы считаете «плохим». Если это означает много кода, вы можете использовать решение @user1641001 (заменив первое на take-while). Если это означает «плохой» в том смысле, что это будет плохо для производительности запросов, как это было бы при использовании SQL, это не так, поскольку ваш запрос выполняется локально на узле. - person stijnopheide; 07.05.2014

В этом случае вам не нужен datomic, так как в вашей последовательности уже есть все необходимые данные. Вместо этого используйте clojure sort.

(first (sort-by second [...]))
person evpozdniakov    schedule 23.04.2014