Macros Clojure Korma:无法运行聚合计数

Macros Clojure Korma:无法运行聚合计数,macros,clojure,korma,Macros,Clojure,Korma,我正在尝试使用Clojure+Korma运行一个简单的查询来提取记录数。 这就是我想做的: (defmacro number-of [ref & filter] `(let [basetmp# (-> (kc/select* ~ref) (kc/aggregate (count :*) :cnt))] (if ~filter (-> basetmp# (kc/where ~filte

我正在尝试使用Clojure+Korma运行一个简单的查询来提取记录数。 这就是我想做的:

(defmacro number-of [ref & filter]
  `(let [basetmp# (-> (kc/select* ~ref)
                      (kc/aggregate (count :*) :cnt))]
     (if ~filter
       (-> basetmp#
           (kc/where ~filter))
       basetmp#)))
但是,如果我尝试使用此宏,则会收到一条错误消息,提示: 传递给以下对象的参数数目错误:核心$count

如果在函数中执行该查询,则该查询将非常有效,但存在一些错误/缺失 在宏中,我无法发现:(

谢谢,
尼科

正如庞佐所指出的,你的计数是错误的

看看宏观扩张

(number-of 'foo)  ;; expands to....

(clojure.core/let [basetmp__9167__auto__ (clojure.core/->
                                          (korma.core/select* 'foo)
                                          (korma.core/aggregate
                                            (clojure.core/count :*)
                                            :cnt))]
  (if nil
    (clojure.core/-> basetmp__9167__auto__ (korma.core/where nil))
    basetmp__9167__auto__))    
因此,您需要防止宏中的计数被扩展为
clojure.core/count
,您可以使用unquote/quote这样做:

(defmacro number-of [ref & filter]
  `(let [basetmp# (-> (kc/select* ~ref)
                      (kc/aggregate (~'count :*) :cnt))]
     (if ~filter
       (-> basetmp#
           (kc/where ~filter))
       basetmp#)))
然后会像预期的那样扩展

(clojure.core/let [basetmp__9137__auto__ (clojure.core/->
                                          (korma.core/select* 'foo)
                                          (korma.core/aggregate
                                            (count :*)
                                            :cnt))]
  (if nil
    (clojure.core/-> basetmp__9137__auto__ (korma.core/where nil))
    basetmp__9137__auto__))
结果SQL看起来合理:

(kc/as-sql (number-of 'foo))
"SELECT COUNT(*) \"cnt\" FROM \"foo\""
更新:
从评论“计数实际代表什么?”-如果您意识到
kc/aggregate
也是一个宏,并且参数是某种类型的“SQL aggregate”DSL,那么您也可以展开
kc/aggregate
调用。您会发现有一个函数,
parse aggregate
,它最终映射到
korma.SQL.fn/agg count

(clojure.core/let [q__2640__auto__ (kc/select* 'foo)]
  (korma.sql.engine/bind-query
    q__2640__auto__
    (clojure.core/let [res__2641__auto__ (korma.core/fields
                                           q__2640__auto__
                                           [(clojure.core/->
                                             q__2640__auto__
                                             (korma.sql.fns/agg-count
                                               :*))
                                            :cnt])]
      (if nil
        (korma.core/group res__2641__auto__ nil)
        res__2641__auto__))))

正如ponzao所指出的,你的计数是错误的

看看宏观扩张

(number-of 'foo)  ;; expands to....

(clojure.core/let [basetmp__9167__auto__ (clojure.core/->
                                          (korma.core/select* 'foo)
                                          (korma.core/aggregate
                                            (clojure.core/count :*)
                                            :cnt))]
  (if nil
    (clojure.core/-> basetmp__9167__auto__ (korma.core/where nil))
    basetmp__9167__auto__))    
因此,您需要防止宏中的计数被扩展为
clojure.core/count
,您可以使用unquote/quote这样做:

(defmacro number-of [ref & filter]
  `(let [basetmp# (-> (kc/select* ~ref)
                      (kc/aggregate (~'count :*) :cnt))]
     (if ~filter
       (-> basetmp#
           (kc/where ~filter))
       basetmp#)))
然后会像预期的那样扩展

(clojure.core/let [basetmp__9137__auto__ (clojure.core/->
                                          (korma.core/select* 'foo)
                                          (korma.core/aggregate
                                            (count :*)
                                            :cnt))]
  (if nil
    (clojure.core/-> basetmp__9137__auto__ (korma.core/where nil))
    basetmp__9137__auto__))
结果SQL看起来合理:

(kc/as-sql (number-of 'foo))
"SELECT COUNT(*) \"cnt\" FROM \"foo\""
更新:
从评论“计数实际代表什么?”-如果您意识到
kc/aggregate
也是一个宏,并且参数是某种类型的“SQL aggregate”DSL,那么您也可以展开
kc/aggregate
调用。您会发现有一个函数,
parse aggregate
,它最终映射到
korma.SQL.fn/agg count

(clojure.core/let [q__2640__auto__ (kc/select* 'foo)]
  (korma.sql.engine/bind-query
    q__2640__auto__
    (clojure.core/let [res__2641__auto__ (korma.core/fields
                                           q__2640__auto__
                                           [(clojure.core/->
                                             q__2640__auto__
                                             (korma.sql.fns/agg-count
                                               :*))
                                            :cnt])]
      (if nil
        (korma.core/group res__2641__auto__ nil)
        res__2641__auto__))))

我认为你的
count
clojure.core/count
而不是Korma的count函数。我认为你的
count
clojure.core/count
而不是Korma的count函数。谢谢你sw1nn。这确实有效,尽管我不完全理解这里的~'的行为。你做了什么(count:*)实际上表示?为什么在评估阶段不执行函数count?我添加了一些关于什么
(count:*)
representsThank you!!现在我明白了。我确实看过聚合的实现,但现在才明白(count)函数并没有真正得到评估,但在编译时被宏替换为agg count!!我应该更仔细地阅读代码;)谢谢sw1nn。尽管我不完全理解~'在这里的行为,但这确实有效。(count:*)实际上代表什么?为什么函数count不能在eval阶段执行?我添加了一些关于什么的进一步说明
(count:*)
表示感谢!!现在我明白了。实际上,我看过aggregate的实现,但直到现在我才明白,(count)函数并没有真正得到评估,而是在编译时被宏替换为agg count!!我应该更仔细地阅读代码;)